http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/rsa_support.c
----------------------------------------------------------------------
diff --git a/version3/c/rsa_support.c b/version3/c/rsa_support.c
new file mode 100644
index 0000000..a4cfdca
--- /dev/null
+++ b/version3/c/rsa_support.c
@@ -0,0 +1,237 @@
+#include "rsa_support.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+int hashit(int sha,octet *p,int n,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (p!=NULL) for (i=0; i<p->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,p->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,p->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,p->val[i]);
+                break;
+            }
+        }
+    if (n>=0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    OCT_jbytes(w,hh,hlen);
+    for (i=0; i<hlen; i++) hh[i]=0;
+
+    return hlen;
+}
+
+/* Mask Generation Function */
+
+static void MGF1(int sha,octet *z,int olen,octet *mask)
+{
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int hlen=sha;
+    int counter,cthreshold;
+
+    OCT_empty(mask);
+
+    cthreshold=ROUNDUP(olen,hlen);
+    for (counter=0; counter<cthreshold; counter++)
+    {
+        hashit(sha,z,counter,&H);
+        if (mask->len+hlen>olen) OCT_jbytes(mask,H.val,olen%hlen);
+        else                     OCT_joctet(mask,&H);
+    }
+    OCT_clear(&H);
+}
+
+/* SHAXXX identifier strings */
+const unsigned char SHA256ID[]= 
{0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+const unsigned char SHA384ID[]= 
{0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+const unsigned char SHA512ID[]= 
{0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+
+int PKCS15(int sha,octet *m,octet *w)
+{
+    int olen=w->max;
+    int hlen=sha;
+    int idlen=19;
+    char h[64];
+    octet H= {0,sizeof(h),h};
+
+    if (olen<idlen+hlen+10) return 1;
+    hashit(sha,m,-1,&H);
+
+    OCT_empty(w);
+    OCT_jbyte(w,0x00,1);
+    OCT_jbyte(w,0x01,1);
+    OCT_jbyte(w,0xff,olen-idlen-hlen-3);
+    OCT_jbyte(w,0x00,1);
+
+    if (hlen==32) OCT_jbytes(w,(char *)SHA256ID,idlen);
+    if (hlen==48) OCT_jbytes(w,(char *)SHA384ID,idlen);
+    if (hlen==64) OCT_jbytes(w,(char *)SHA512ID,idlen);
+
+    OCT_joctet(w,&H);
+
+    return 0;
+}
+
+/* OAEP Message Encoding for Encryption */
+
+int OAEP_ENCODE(int sha,octet *m,csprng *RNG,octet *p,octet *f)
+{
+    int slen,olen=f->max-1;
+    int mlen=m->len;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+
+    hlen=seedlen=sha;
+    if (mlen>olen-hlen-seedlen-1) return 1;
+    if (m==f) return 1;  /* must be distinct octets */
+
+    hashit(sha,p,-1,f);
+
+    slen=olen-mlen-hlen-seedlen-1;
+
+    OCT_jbyte(f,0,slen);
+    OCT_jbyte(f,0x1,1);
+    OCT_joctet(f,m);
+
+    OCT_rand(&SEED,RNG,seedlen);
+
+    MGF1(sha,&SEED,olen-seedlen,&DBMASK);
+
+    OCT_xor(&DBMASK,f);
+    MGF1(sha,&DBMASK,seedlen,f);
+
+    OCT_xor(f,&SEED);
+
+    OCT_joctet(f,&DBMASK);
+
+    OCT_pad(f,f->max);
+    OCT_clear(&SEED);
+    OCT_clear(&DBMASK);
+
+    return 0;
+}
+
+/* OAEP Message Decoding for Decryption */
+
+int OAEP_DECODE(int sha,octet *p,octet *f)
+{
+    int comp,x,t;
+    int i,k,olen=f->max-1;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64],chash[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+    octet CHASH= {0,sizeof(chash),chash};
+
+    seedlen=hlen=sha;
+    if (olen<seedlen+hlen+1) return 1;
+    if (!OCT_pad(f,olen+1)) return 1;
+    hashit(sha,p,-1,&CHASH);
+
+    x=f->val[0];
+    for (i=seedlen; i<olen; i++)
+        DBMASK.val[i-seedlen]=f->val[i+1];
+    DBMASK.len=olen-seedlen;
+
+    MGF1(sha,&DBMASK,seedlen,&SEED);
+    for (i=0; i<seedlen; i++) SEED.val[i]^=f->val[i+1];
+    MGF1(sha,&SEED,olen-seedlen,f);
+    OCT_xor(&DBMASK,f);
+
+    comp=OCT_ncomp(&CHASH,&DBMASK,hlen);
+
+    OCT_shl(&DBMASK,hlen);
+
+    OCT_clear(&SEED);
+    OCT_clear(&CHASH);
+
+    for (k=0;; k++)
+    {
+        if (k>=DBMASK.len)
+        {
+            OCT_clear(&DBMASK);
+            return 1;
+        }
+        if (DBMASK.val[k]!=0) break;
+    }
+
+    t=DBMASK.val[k];
+    if (!comp || x!=0 || t!=0x01)
+    {
+        OCT_clear(&DBMASK);
+        return 1;
+    }
+
+    OCT_shl(&DBMASK,k+1);
+    OCT_copy(f,&DBMASK);
+    OCT_clear(&DBMASK);
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/rsa_support.h
----------------------------------------------------------------------
diff --git a/version3/c/rsa_support.h b/version3/c/rsa_support.h
new file mode 100644
index 0000000..3bd495f
--- /dev/null
+++ b/version3/c/rsa_support.h
@@ -0,0 +1,62 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+/**
+ * @file rsa_support.h
+ * @author Mike Scott
+ * @brief RSA Support  Header File
+ *
+ */
+
+#ifndef RSA_SUPPORT_H
+#define RSA_SUPPORT_H
+
+#include "amcl.h"
+
+#define MAX_RSA_BYTES 512 /**< Maximum of 4096 */
+
+/**    @brief PKCS V1.5 padding of a message prior to RSA signature
+ *
+       @param h is the hash type
+       @param M is the input message
+       @param W is the output encoding, ready for RSA signature
+       @return 1 if OK, else 0
+ */
+extern int PKCS15(int h,octet *M,octet *W);
+/**    @brief OAEP padding of a message prior to RSA encryption
+ *
+       @param h is the hash type
+       @param M is the input message
+       @param R is a pointer to a cryptographically secure random number 
generator
+       @param P are input encoding parameter string (could be NULL)
+       @param F is the output encoding, ready for RSA encryption
+       @return 1 if OK, else 0
+ */
+extern int     OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
+/**    @brief OAEP unpadding of a message after RSA decryption
+ *
+       Unpadding is done in-place
+       @param h is the hash type
+       @param P are input encoding parameter string (could be NULL)
+       @param F is input padded message, unpadded on output
+       @return 1 if OK, else 0
+ */
+extern int  OAEP_DECODE(int h,octet *P,octet *F);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/testall.c
----------------------------------------------------------------------
diff --git a/version3/c/testall.c b/version3/c/testall.c
new file mode 100644
index 0000000..da8e034
--- /dev/null
+++ b/version3/c/testall.c
@@ -0,0 +1,1627 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ecdh_ED25519.h"
+#include "mpin_BN254.h"
+#include "rsa_2048.h"
+#include "randapi.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "ecdh_NIST256.h"
+#include "ecdh_GOLDILOCKS.h"
+#include "mpin_BLS383.h"
+#include "mpin192_BLS24.h"
+#include "mpin256_BLS48.h"
+#endif
+
+int ecdh_ED25519(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow 
attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 
appended block 
+    // Recall EFS_ED25519 is field size in bytes. So EFS_ED25519=32 for 
256-bit curve 
+    char 
s0[2*EGS_ED25519],s1[EGS_ED25519],w0[2*EFS_ED25519+1],w1[2*EFS_ED25519+1],z0[EFS_ED25519],z1[EFS_ED25519],key[AESKEY_ED25519],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_ED25519 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_ED25519,&PW,&SALT,1000,EGS_ED25519,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_ED25519_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_ED25519_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_ED25519_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_ED25519_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_ED25519_SVDP_DH(&S0,&W1,&Z0);
+    ECP_ED25519_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_ED25519,&Z0,NULL,AESKEY_ED25519,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_ED25519 != MONTGOMERY
+
+    char 
ds[EGS_ED25519],p1[30],p2[30],v[2*EFS_ED25519+1],m[32],c[64],t[32],cs[EGS_ED25519];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    
ECP_ED25519_ECIES_ENCRYPT(HASH_TYPE_ED25519,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ED25519_ECIES_DECRYPT(HASH_TYPE_ED25519,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_ED25519_SP_DSA(HASH_TYPE_ED25519,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_ED25519_VP_DSA(HASH_TYPE_ED25519,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+int ecdh_NIST256(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow 
attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 
appended block 
+    // Recall EFS_NIST256 is field size in bytes. So EFS_NIST256=32 for 
256-bit curve 
+    char 
s0[2*EGS_NIST256],s1[EGS_NIST256],w0[2*EFS_NIST256+1],w1[2*EFS_NIST256+1],z0[EFS_NIST256],z1[EFS_NIST256],key[AESKEY_NIST256],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_NIST256 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_NIST256,&PW,&SALT,1000,EGS_NIST256,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_NIST256_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_NIST256_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_NIST256_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_NIST256_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_NIST256_SVDP_DH(&S0,&W1,&Z0);
+    ECP_NIST256_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_NIST256,&Z0,NULL,AESKEY_NIST256,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_NIST256 != MONTGOMERY
+
+    char 
ds[EGS_NIST256],p1[30],p2[30],v[2*EFS_NIST256+1],m[32],c[64],t[32],cs[EGS_NIST256];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    
ECP_NIST256_ECIES_ENCRYPT(HASH_TYPE_NIST256,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_NIST256_ECIES_DECRYPT(HASH_TYPE_NIST256,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_NIST256_SP_DSA(HASH_TYPE_NIST256,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_NIST256_VP_DSA(HASH_TYPE_NIST256,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+int ecdh_GOLDILOCKS(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow 
attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 
appended block 
+    // Recall EFS_GOLDILOCKS is field size in bytes. So EFS_GOLDILOCKS=32 for 
256-bit curve 
+    char 
s0[2*EGS_GOLDILOCKS],s1[EGS_GOLDILOCKS],w0[2*EFS_GOLDILOCKS+1],w1[2*EFS_GOLDILOCKS+1],z0[EFS_GOLDILOCKS],z1[EFS_GOLDILOCKS],key[AESKEY_GOLDILOCKS],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_GOLDILOCKS bytes derived from Password and 
Salt 
+
+    PBKDF2(HASH_TYPE_GOLDILOCKS,&PW,&SALT,1000,EGS_GOLDILOCKS,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_GOLDILOCKS_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_GOLDILOCKS_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_GOLDILOCKS_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_GOLDILOCKS_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_GOLDILOCKS_SVDP_DH(&S0,&W1,&Z0);
+    ECP_GOLDILOCKS_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_GOLDILOCKS,&Z0,NULL,AESKEY_GOLDILOCKS,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_GOLDILOCKS != MONTGOMERY
+
+    char 
ds[EGS_GOLDILOCKS],p1[30],p2[30],v[2*EFS_GOLDILOCKS+1],m[32],c[64],t[32],cs[EGS_GOLDILOCKS];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    
ECP_GOLDILOCKS_ECIES_ENCRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if 
(!ECP_GOLDILOCKS_ECIES_DECRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_GOLDILOCKS_SP_DSA(HASH_TYPE_GOLDILOCKS,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_GOLDILOCKS_VP_DSA(HASH_TYPE_GOLDILOCKS,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+#endif
+
+#define PERMITS  // for time permits ON or OFF 
+#define PINERROR // For PIN ERROR detection ON or OFF 
+#define FULL     // for M-Pin Full or M-Pin regular 
+
+int mpin_BN254(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char 
x[PGS_BN254],s[PGS_BN254],y[PGS_BN254],client_id[100],sst[4*PFS_BN254],token[2*PFS_BN254+1],sec[2*PFS_BN254+1],permit[2*PFS_BN254+1],xcid[2*PFS_BN254+1],xid[2*PFS_BN254+1],e[12*PFS_BN254],f[12*PFS_BN254];
+    char 
hcid[PFS_BN254],hsid[PFS_BN254],hid[2*PFS_BN254+1],htid[2*PFS_BN254+1],h[PGS_BN254];
+#ifdef FULL
+    char r[PGS_BN254],z[2*PFS_BN254+1],w[PGS_BN254],t[2*PFS_BN254+1];
+    char g1[12*PFS_BN254],g2[12*PFS_BN254];
+    char ck[AESKEY_BN254],sk[AESKEY_BN254];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BN254_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"[email protected]");
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);  // Either Client or TA 
calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BN254_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BN254_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BN254_EXTRACT_PIN(HASH_TYPE_BN254,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BN254_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BN254_GET_CLIENT_PERMIT(HASH_TYPE_BN254,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BN254_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BN254_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // Set date=0 and PERMIT=NULL if time permits not in use
+
+   // Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and 
PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
+   // If PERMITS are is use, then date!=0 and PERMIT is added to secret and 
xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
+   // Random value x is supplied externally if RNG=NULL, otherwise generated 
and passed out by RNG
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // IMPORTANT: To save space and time..
+   // If Time Permits OFF set xCID = NULL, HTID=NULL and use xID and HID only
+   // If Time permits are ON, AND pin error detection is required then all of 
xID, xCID, HID and HTID are required
+   // If Time permits are ON, AND pin error detection is NOT required, set 
xID=NULL, HID=NULL and use xCID and HTID only.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BN254_GET_TIME();
+
+    
rtn=MPIN_BN254_CLIENT(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BN254_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r 
+#endif
+
+
+    
rtn=MPIN_BN254_SERVER(HASH_TYPE_BN254,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID);  // new
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if 
(MPIN_BN254_CLIENT_1(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), 
and maps them to points on the curve HID and HTID resp. 
+    MPIN_BN254_SERVER_1(HASH_TYPE_BN254,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BN254_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID); //new
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs 
-(x+y)*SEC 
+    if (MPIN_BN254_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. Inputs hashed client id, random Y, -(x+y)*SEC, xID 
and xCID and Server secret SST. E and F help kangaroos to find error. 
+    // If PIN error not required, set E and F = NULL 
+    
rtn=MPIN_BN254_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BN254_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BN254,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BN254_CLIENT_KEY(HASH_TYPE_BN254,&G1,&G2,pin,&R,&X,&H,&T,&CK);      
// new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BN254,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BN254_SERVER_KEY(HASH_TYPE_BN254,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); 
// new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int mpin_BLS383(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char 
x[PGS_BLS383],s[PGS_BLS383],y[PGS_BLS383],client_id[100],sst[4*PFS_BLS383],token[2*PFS_BLS383+1],sec[2*PFS_BLS383+1],permit[2*PFS_BLS383+1],xcid[2*PFS_BLS383+1],xid[2*PFS_BLS383+1],e[12*PFS_BLS383],f[12*PFS_BLS383];
+    char 
hcid[PFS_BLS383],hsid[PFS_BLS383],hid[2*PFS_BLS383+1],htid[2*PFS_BLS383+1],h[PGS_BLS383];
+#ifdef FULL
+    char r[PGS_BLS383],z[2*PFS_BLS383+1],w[PGS_BLS383],t[2*PFS_BLS383+1];
+    char g1[12*PFS_BLS383],g2[12*PFS_BLS383];
+    char ck[AESKEY_BLS383],sk[AESKEY_BLS383];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS383_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"[email protected]");
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);  // Either Client or TA 
calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS383_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS383_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS383_EXTRACT_PIN(HASH_TYPE_BLS383,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS383_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS383_GET_CLIENT_PERMIT(HASH_TYPE_BLS383,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS383_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS383_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // Set date=0 and PERMIT=NULL if time permits not in use
+
+   // Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and 
PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
+   // If PERMITS are is use, then date!=0 and PERMIT is added to secret and 
xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
+   // Random value x is supplied externally if RNG=NULL, otherwise generated 
and passed out by RNG
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // IMPORTANT: To save space and time..
+   // If Time Permits OFF set xCID = NULL, HTID=NULL and use xID and HID only
+   // If Time permits are ON, AND pin error detection is required then all of 
xID, xCID, HID and HTID are required
+   // If Time permits are ON, AND pin error detection is NOT required, set 
xID=NULL, HID=NULL and use xCID and HTID only.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS383_GET_TIME();
+
+    
rtn=MPIN_BLS383_CLIENT(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS383_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r 
+#endif
+
+
+    
rtn=MPIN_BLS383_SERVER(HASH_TYPE_BLS383,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if 
(MPIN_BLS383_CLIENT_1(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), 
and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS383_SERVER_1(HASH_TYPE_BLS383,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS383_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID); //new
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs 
-(x+y)*SEC 
+    if (MPIN_BLS383_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. Inputs hashed client id, random Y, -(x+y)*SEC, xID 
and xCID and Server secret SST. E and F help kangaroos to find error. 
+    // If PIN error not required, set E and F = NULL 
+    
rtn=MPIN_BLS383_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS383_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS383,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS383_CLIENT_KEY(HASH_TYPE_BLS383,&G1,&G2,pin,&R,&X,&H,&T,&CK);      
// new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS383,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    
MPIN_BLS383_SERVER_KEY(HASH_TYPE_BLS383,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // 
new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+int mpin192_BLS24(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char 
x[PGS_BLS24],s[PGS_BLS24],y[PGS_BLS24],client_id[100],sst[8*PFS_BLS24],token[2*PFS_BLS24+1],sec[2*PFS_BLS24+1],permit[2*PFS_BLS24+1],xcid[2*PFS_BLS24+1],xid[2*PFS_BLS24+1],e[24*PFS_BLS24],f[24*PFS_BLS24];
+    char 
hcid[PFS_BLS24],hsid[PFS_BLS24],hid[2*PFS_BLS24+1],htid[2*PFS_BLS24+1],h[PGS_BLS24];
+#ifdef FULL
+    char r[PGS_BLS24],z[2*PFS_BLS24+1],w[PGS_BLS24],t[2*PFS_BLS24+1];
+    char g1[24*PFS_BLS24],g2[24*PFS_BLS24];
+    char ck[AESKEY_BLS24],sk[AESKEY_BLS24];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS24_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"[email protected]");
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);  // Either Client or TA 
calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS24_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS24_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS24_EXTRACT_PIN(HASH_TYPE_BLS24,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS24_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS24_GET_CLIENT_PERMIT(HASH_TYPE_BLS24,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS24_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS24_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // Set date=0 and PERMIT=NULL if time permits not in use
+
+   // Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and 
PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
+   // If PERMITS are is use, then date!=0 and PERMIT is added to secret and 
xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
+   // Random value x is supplied externally if RNG=NULL, otherwise generated 
and passed out by RNG
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // IMPORTANT: To save space and time..
+   // If Time Permits OFF set xCID = NULL, HTID=NULL and use xID and HID only
+   // If Time permits are ON, AND pin error detection is required then all of 
xID, xCID, HID and HTID are required
+   // If Time permits are ON, AND pin error detection is NOT required, set 
xID=NULL, HID=NULL and use xCID and HTID only.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS24_GET_TIME();
+
+    
rtn=MPIN_BLS24_CLIENT(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS24_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r 
+#endif
+
+
+    
rtn=MPIN_BLS24_SERVER(HASH_TYPE_BLS24,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if 
(MPIN_BLS24_CLIENT_1(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), 
and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS24_SERVER_1(HASH_TYPE_BLS24,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS24_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID); //new
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs 
-(x+y)*SEC 
+    if (MPIN_BLS24_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. Inputs hashed client id, random Y, -(x+y)*SEC, xID 
and xCID and Server secret SST. E and F help kangaroos to find error. 
+    // If PIN error not required, set E and F = NULL 
+    
rtn=MPIN_BLS24_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS24_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS24,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS24_CLIENT_KEY(HASH_TYPE_BLS24,&G1,&G2,pin,&R,&X,&H,&T,&CK);      
// new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS24,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BLS24_SERVER_KEY(HASH_TYPE_BLS24,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); 
// new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+int mpin256_BLS48(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char 
x[PGS_BLS48],s[PGS_BLS48],y[PGS_BLS48],client_id[100],sst[16*PFS_BLS48],token[2*PFS_BLS48+1],sec[2*PFS_BLS48+1],permit[2*PFS_BLS48+1],xcid[2*PFS_BLS48+1],xid[2*PFS_BLS48+1],e[48*PFS_BLS48],f[48*PFS_BLS48];
+    char 
hcid[PFS_BLS48],hsid[PFS_BLS48],hid[2*PFS_BLS48+1],htid[2*PFS_BLS48+1],h[PGS_BLS48];
+#ifdef FULL
+    char r[PGS_BLS48],z[2*PFS_BLS48+1],w[PGS_BLS48],t[2*PFS_BLS48+1];
+    char g1[48*PFS_BLS48],g2[48*PFS_BLS48];
+    char ck[AESKEY_BLS48],sk[AESKEY_BLS48];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS48_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"[email protected]");
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);  // Either Client or TA 
calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS48_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS48_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS48_EXTRACT_PIN(HASH_TYPE_BLS48,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS48_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS48_GET_CLIENT_PERMIT(HASH_TYPE_BLS48,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS48_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS48_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // Set date=0 and PERMIT=NULL if time permits not in use
+
+   // Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and 
PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
+   // If PERMITS are is use, then date!=0 and PERMIT is added to secret and 
xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
+   // Random value x is supplied externally if RNG=NULL, otherwise generated 
and passed out by RNG
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // IMPORTANT: To save space and time..
+   // If Time Permits OFF set xCID = NULL, HTID=NULL and use xID and HID only
+   // If Time permits are ON, AND pin error detection is required then all of 
xID, xCID, HID and HTID are required
+   // If Time permits are ON, AND pin error detection is NOT required, set 
xID=NULL, HID=NULL and use xCID and HTID only.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS48_GET_TIME();
+
+    
rtn=MPIN_BLS48_CLIENT(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS48_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r 
+#endif
+
+
+    
rtn=MPIN_BLS48_SERVER(HASH_TYPE_BLS48,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if 
(MPIN_BLS48_CLIENT_1(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to 
Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), 
and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS48_SERVER_1(HASH_TYPE_BLS48,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS48_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID); //new
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to 
client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs 
-(x+y)*SEC 
+    if (MPIN_BLS48_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. Inputs hashed client id, random Y, -(x+y)*SEC, xID 
and xCID and Server secret SST. E and F help kangaroos to find error. 
+    // If PIN error not required, set E and F = NULL 
+    
rtn=MPIN_BLS48_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS48_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS48,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS48_CLIENT_KEY(HASH_TYPE_BLS48,&G1,&G2,pin,&R,&X,&H,&T,&CK);      
// new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS48,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BLS48_SERVER_KEY(HASH_TYPE_BLS48,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); 
// new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+#endif
+
+int rsa_2048(csprng *RNG)
+{
+    int i;
+    unsigned long ran;
+    char m[RFS_2048],ml[RFS_2048],c[RFS_2048],e[RFS_2048],s[RFS_2048];
+    rsa_public_key_2048 pub;
+    rsa_private_key_2048 priv;
+    
+    octet M= {0,sizeof(m),m};
+    octet ML= {0,sizeof(ml),ml};
+    octet C= {0,sizeof(c),c};
+    octet E= {0,sizeof(e),e};
+    octet S= {0,sizeof(s),s};
+
+    printf("Generating public/private key pair\n");
+    RSA_2048_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+
+    printf("Encrypting test string\n");
+    OCT_jstring(&M,(char *)"Hello World\n");
+
+    OAEP_ENCODE(HASH_TYPE_RSA_2048,&M,RNG,NULL,&E); // OAEP encode message m 
to e  
+
+    RSA_2048_ENCRYPT(&pub,&E,&C);     // encrypt encoded message 
+    printf("Ciphertext= ");
+    OCT_output(&C);
+
+    printf("Decrypting test string\n");
+    RSA_2048_DECRYPT(&priv,&C,&ML);   // ... and then decrypt it 
+
+    OAEP_DECODE(HASH_TYPE_RSA_2048,NULL,&ML);    // decode it 
+    OCT_output_string(&ML);
+
+    printf("Signing message\n");
+    PKCS15(HASH_TYPE_RSA_2048,&M,&C);
+
+    RSA_2048_DECRYPT(&priv,&C,&S); // create signature in S 
+
+    printf("Signature= ");
+    OCT_output(&S);
+
+    RSA_2048_ENCRYPT(&pub,&S,&ML);
+
+    if (OCT_comp(&C,&ML)) printf("Signature is valid\n");
+    else printf("Signature is INVALID\n");
+
+    RSA_2048_PRIVATE_KEY_KILL(&priv);
+
+    OCT_clear(&M);
+    OCT_clear(&ML);   // clean up afterwards 
+    OCT_clear(&C);
+    OCT_clear(&E);
+
+    return 0;
+}
+
+
+int main()
+{
+    int i,res;
+    unsigned long ran;
+
+       char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                // Crypto Strong RNG 
+
+    time((time_t *)&ran);
+
+    RAW.len=100;                               // fake random seed source 
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=4; i<100; i++) RAW.val[i]=i;
+
+    CREATE_CSPRNG(&RNG,&RAW);   // initialise strong RNG 
+
+       printf("\nTesting MPIN protocols for curve BN254\n");
+       mpin_BN254(&RNG);
+
+#if CHUNK!=16
+    printf("\nTesting MPIN protocols for curve BLS383\n");
+    mpin_BLS383(&RNG);
+    printf("\nTesting MPIN protocols for curve BLS24\n");
+    mpin192_BLS24(&RNG);
+    printf("\nTesting MPIN protocols for curve BLS48\n");
+    mpin256_BLS48(&RNG);
+#endif
+
+
+       printf("\nTesting ECDH protocols for curve ED25519\n");
+       ecdh_ED25519(&RNG);
+#if CHUNK!=16
+       printf("\nTesting ECDH protocols for curve NIST256\n");
+       ecdh_NIST256(&RNG);
+       printf("\nTesting ECDH protocols for curve GOLDILOCKS\n");
+       ecdh_GOLDILOCKS(&RNG);
+#endif
+       printf("\nTesting RSA protocols for 2048-bit RSA\n");
+       rsa_2048(&RNG);
+
+       KILL_CSPRNG(&RNG);
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/testbls.c
----------------------------------------------------------------------
diff --git a/version3/c/testbls.c b/version3/c/testbls.c
new file mode 100644
index 0000000..ae71a25
--- /dev/null
+++ b/version3/c/testbls.c
@@ -0,0 +1,189 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* test driver and function exerciser for BLS Signature API Functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "bls_BN254.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "bls_BLS383.h"
+#include "bls192_BLS24.h"
+#include "bls256_BLS48.h"
+#endif
+
+#include "randapi.h"
+
+static char message[]="This is a test message";
+
+int bls_BN254(csprng *RNG)
+{
+       int res;
+    char s[BGS_BN254],w[4*BFS_BN254],sig[BFS_BN254+1];
+       octet S= {0,sizeof(s),s};
+    octet W= {0,sizeof(w),w};
+       octet SIG= {0,sizeof(sig),sig}; 
+
+       BLS_BN254_KEY_PAIR_GENERATE(RNG,&S,&W);
+
+       printf("Private key= 0x");
+    OCT_output(&S);
+       printf("Public key= 0x");
+    OCT_output(&W);
+
+       BLS_BN254_SIGN(&SIG,message,&S);
+       printf("Signature= 0x");
+    OCT_output(&SIG);
+
+       //message[7]='f'; // change the message
+
+       res=BLS_BN254_VERIFY(&SIG,message,&W);
+       if (res==BLS_OK) printf("Signature is OK\n");
+       else printf("Signature is *NOT* OK\n");
+       return res;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int bls_BLS383(csprng *RNG)
+{
+       int res;
+    char s[BGS_BLS383],w[4*BFS_BLS383],sig[BFS_BLS383+1];
+       octet S= {0,sizeof(s),s};
+    octet W= {0,sizeof(w),w};
+       octet SIG= {0,sizeof(sig),sig}; 
+
+       BLS_BLS383_KEY_PAIR_GENERATE(RNG,&S,&W);
+
+       printf("Private key= 0x");
+    OCT_output(&S);
+       printf("Public key= 0x");
+    OCT_output(&W);
+
+       BLS_BLS383_SIGN(&SIG,message,&S);
+       printf("Signature= 0x");
+    OCT_output(&SIG);
+
+       //message[7]='f'; // change the message
+
+       res=BLS_BLS383_VERIFY(&SIG,message,&W);
+       if (res==BLS_OK) printf("Signature is OK\n");
+       else printf("Signature is *NOT* OK\n");
+       return res;
+}
+
+int bls_BLS24(csprng *RNG)
+{
+       int res;
+    char s[BGS_BLS24],w[8*BFS_BLS24],sig[BFS_BLS24+1];
+       octet S= {0,sizeof(s),s};
+    octet W= {0,sizeof(w),w};
+       octet SIG= {0,sizeof(sig),sig}; 
+
+       BLS_BLS24_KEY_PAIR_GENERATE(RNG,&S,&W);
+
+       printf("Private key= 0x");
+    OCT_output(&S);
+       printf("Public key= 0x");
+    OCT_output(&W);
+
+       BLS_BLS24_SIGN(&SIG,message,&S);
+       printf("Signature= 0x");
+    OCT_output(&SIG);
+
+       //message[7]='f'; // change the message
+
+       res=BLS_BLS24_VERIFY(&SIG,message,&W);
+       if (res==BLS_OK) printf("Signature is OK\n");
+       else printf("Signature is *NOT* OK\n");
+       return res;
+}
+
+int bls_BLS48(csprng *RNG)
+{
+       int res;
+    char s[BGS_BLS48],w[16*BFS_BLS48],sig[BFS_BLS48+1];
+       octet S= {0,sizeof(s),s};
+    octet W= {0,sizeof(w),w};
+       octet SIG= {0,sizeof(sig),sig}; 
+
+       BLS_BLS48_KEY_PAIR_GENERATE(RNG,&S,&W);
+
+       printf("Private key= 0x");
+    OCT_output(&S);
+       printf("Public key= 0x");
+    OCT_output(&W);
+
+       BLS_BLS48_SIGN(&SIG,message,&S);
+       printf("Signature= 0x");
+    OCT_output(&SIG);
+
+       //message[7]='f'; // change the message
+
+       res=BLS_BLS48_VERIFY(&SIG,message,&W);
+       if (res==BLS_OK) printf("Signature is OK\n");
+       else printf("Signature is *NOT* OK\n");
+       return res;
+}
+
+#endif
+
+int main()
+{
+    int i,res;
+    unsigned long ran;
+
+       char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                // Crypto Strong RNG 
+
+    time((time_t *)&ran);
+
+    RAW.len=100;                               // fake random seed source 
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=4; i<100; i++) RAW.val[i]=i;
+
+    CREATE_CSPRNG(&RNG,&RAW);   // initialise strong RNG 
+
+       printf("%d bit build\n",CHUNK);
+
+       printf("Testing BLS signature for curve BN254\n");
+       bls_BN254(&RNG);
+
+#if CHUNK!=16
+       printf("\nTesting BLS signature for curve BLS383\n");
+       bls_BLS383(&RNG);
+
+       printf("\nTesting BLS signature for curve BLS24\n");
+       bls_BLS24(&RNG);
+
+       printf("\nTesting BLS signature for curve BLS48\n");
+       bls_BLS48(&RNG);
+#endif
+
+       KILL_CSPRNG(&RNG);
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/testnhs.c
----------------------------------------------------------------------
diff --git a/version3/c/testnhs.c b/version3/c/testnhs.c
new file mode 100644
index 0000000..dca7925
--- /dev/null
+++ b/version3/c/testnhs.c
@@ -0,0 +1,71 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* test driver and function exerciser for NewHope Functions */
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+/* gcc -O2 testnhs.c amcl.a -o testnhs.exe */
+
+#include <stdio.h>
+#include <time.h>
+#include "newhope.h"
+
+int main()
+{
+       int i,ii,j,err;
+    unsigned long ran;
+       char raw[100];
+       csprng SRNG,CRNG;
+       RAND_clean(&SRNG); RAND_clean(&CRNG);
+       char s[1792],sb[1824],uc[2176],keyA[32],keyB[32];
+
+       octet S= {0,sizeof(s),s};
+       octet SB= {0,sizeof(sb),sb};
+       octet UC= {0,sizeof(uc),uc};
+       octet KEYA={0,sizeof(keyA),keyA};
+       octet KEYB={0,sizeof(keyB),keyB};
+
+// initialise random number generators
+    time((time_t *)&ran);
+
+    raw[0]=ran;
+    raw[1]=ran>>8;
+    raw[2]=ran>>16;
+    raw[3]=ran>>24;
+
+       for (i=4;i<100;i++) raw[i]=i+1;
+       RAND_seed(&SRNG,100,raw);
+                                                                               
for (i=4;i<100;i++) raw[i]=i+2;
+                                                                               
RAND_seed(&CRNG,100,raw);
+// NewHope Simple key exchange
+
+       NHS_SERVER_1(&SRNG,&SB,&S);
+                                                                               
NHS_CLIENT(&CRNG,&SB,&UC,&KEYB);
+       NHS_SERVER_2(&S,&UC,&KEYA);
+
+    printf("Alice key= 0x");
+    OCT_output(&KEYA);
+                                                                               
printf("Bob's key= 0x");
+                                                                               
OCT_output(&KEYB);
+
+       return 0;
+}
+
+

Reply via email to