http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/mpin192.h ---------------------------------------------------------------------- diff --git a/version3/c/mpin192.h b/version3/c/mpin192.h new file mode 100644 index 0000000..79f562c --- /dev/null +++ b/version3/c/mpin192.h @@ -0,0 +1,339 @@ +/* +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 mpin.h + * @author Mike Scott and Kealan McCusker + * @date 2nd June 2015 + * @brief M-Pin Header file + * + * Allows some user configuration + * defines structures + * declares functions + * + */ + +#ifndef MPIN_ZZZ_H +#define MPIN_ZZZ_H + +#include "pair192_ZZZ.h" +#include "pbc_support.h" + +/* Field size is assumed to be greater than or equal to group size */ + +#define PGS_ZZZ MODBYTES_XXX /**< MPIN Group Size */ +#define PFS_ZZZ MODBYTES_XXX /**< MPIN Field Size */ + +#define MPIN_OK 0 /**< Function completed without error */ +#define MPIN_INVALID_POINT -14 /**< Point is NOT on the curve */ +#define MPIN_BAD_PIN -19 /**< Bad PIN number entered */ + +#define MAXPIN 10000 /**< max PIN */ +#define PBLEN 14 /**< max length of PIN in bits */ + +//#define PAS_ZZZ 24 /**< MPIN Symmetric Key Size 192 bits */ +//#define HASH_TYPE_MPIN_ZZZ SHA384 /**< Choose Hash function */ + +#define MESSAGE_SIZE 256 /**< Signature message size */ +#define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1) /**< Signature message size and G1 size */ + + +/* MPIN support functions */ + +/* MPIN primitives */ + + +void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y); +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param factor is an input factor + @param facbits is the number of bits in the factor + @param CS is the client secret from which the factor is to be extracted + @return 0 or an error code + */ +int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS); + +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param factor is an input factor + @param facbits is the number of bits in the factor + @param CS is the client secret to which the factor is to be added + @return 0 or an error code + */ +int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS); + + +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param pin is an input PIN number + @param CS is the client secret from which the PIN is to be extracted + @return 0 or an error code + */ +int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS); + +/** @brief Perform client side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y); +/** @brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP); +/** @brief Generate a random group element + * + @param R is a pointer to a cryptographically secure random number generator + @param S is the output random octet + @return 0 or an error code + */ +int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S); +/** @brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol + * + @param x an input, a locally generated random number + @param y an input random challenge from the server + @param V on output = -(x+y).V + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V); +/** @brief Perform server side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param ID is the input claimed client identity + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa); +/** @brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol + * + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input claimed client identity + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @return 0 or an error code + */ +void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID); +/** @brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is input H(ID), a hash of the client ID + @param HTID is input H(ID)+H(d|H(ID)) + @param y is the input server's randomly generated challenge + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa); +/** @brief Add two members from the group G1 + * + @param Q1 an input member of G1 + @param Q2 an input member of G1 + @param Q an output member of G1 = Q1+Q2 + @return 0 or an error code + */ +int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q); +/** @brief Add two members from the group G2 + * + @param P1 an input member of G2 + @param P2 an input member of G2 + @param P an output member of G2 = P1+P2 + @return 0 or an error code + */ +int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P); +/** @brief Use Kangaroos to find PIN error + * + @param E a member of the group GT + @param F a member of the group GT = E^e + @return 0 if Kangaroos failed, or the PIN error e + */ +int MPIN_ZZZ_KANGAROO(octet *E,octet *F); +/** @brief Encoding of a Time Permit to make it indistinguishable from a random string + * + @param R is a pointer to a cryptographically secure random number generator + @param TP is the input time permit, obfuscated on output + @return 0 or an error code + */ +int MPIN_ZZZ_ENCODING(csprng *R,octet *TP); +/** @brief Encoding of an obfuscated Time Permit + * + @param TP is the input obfuscated time permit, restored on output + @return 0 or an error code + */ +int MPIN_ZZZ_DECODING(octet *TP); + +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to be taken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G if type=0 a point in G1, else an octet to be mapped to G1 + @param W the output =x.G or x.M(G), where M(.) is a mapping + @return 0 or an error code + */ +int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to betaken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G a point in G2 + @param W the output =x.G or (1/x).G + @return 0 or an error code + */ +int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); + +/** @brief Create a client secret in G1 from a master secret and the client ID + * + @param S is an input master secret + @param ID is the input client identity + @param CS is the full client secret = s.H(ID) + @return 0 or an error code + */ +int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS); +/** @brief Create a Time Permit in G1 from a master secret and the client ID + * + @param h is the hash type + @param d is input date, in days since the epoch. + @param S is an input master secret + @param ID is the input client identity + @param TP is a Time Permit for the given date = s.H(d|H(ID)) + @return 0 or an error code + */ +int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP); +/** @brief Create a server secret in G2 from a master secret + * + @param S is an input master secret + @param SS is the server secret = s.Q where Q is a fixed generator of G2 + @return 0 or an error code + */ +int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS); +/* int MPIN_TEST_PAIRING(octet *,octet *); */ + +/* For M-Pin Full */ +/** @brief Precompute values for use by the client side of M-Pin Full + * + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param ID is the input client identity + @param CP is Public Key (or NULL) + @param g1 precomputed output + @param g2 precomputed output + @return 0 or an error code + */ +int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2); +/** @brief Calculate Key on Server side for M-Pin Full + * + Uses UT internally for the key calculation, unless not available in which case U is used + @param h is the hash type + @param Z is the input Client-side Diffie-Hellman component + @param SS is the input server secret + @param w is an input random number generated by the server + @param p is an input, hash of the protocol transcript + @param I is the hashed input client ID = H(ID) + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K); +/** @brief Calculate Key on Client side for M-Pin Full + * + @param h is the hash type + @param g1 precomputed input + @param g2 precomputed input + @param pin is the input PIN number + @param r is an input, a locally generated random number + @param x is an input, a locally generated random number + @param p is an input, hash of the protocol transcript + @param T is the input Server-side Diffie-Hellman component + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K); + +/** @brief Generates a random public key for the client z.Q + * + @param R is a pointer to a cryptographically secure random number generator + @param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input + @param Pa the output public key for the client + */ +int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa); + +#endif +
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/mpin256.c ---------------------------------------------------------------------- diff --git a/version3/c/mpin256.c b/version3/c/mpin256.c new file mode 100644 index 0000000..d8d9ea3 --- /dev/null +++ b/version3/c/mpin256.c @@ -0,0 +1,967 @@ +/* +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. +*/ + +/* MPIN Functions */ + +/* Version 3.0 - supports Time Permits */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "mpin256_ZZZ.h" + + +#define ROUNDUP(a,b) ((a)-1)/(b)+1 + + +/* Special mpin hashing */ +static void mpin_hash(int sha,FP16_YYY *f, ECP_ZZZ *P,octet *w) +{ + int i; + BIG_XXX x,y; + char h[64]; + hash256 sha256; + hash512 sha512; + char t[18*MODBYTES_XXX]; // to hold 10 BIGs + int hlen=sha; + + FP_YYY_redc(x,&(f->a.a.a.a)); + BIG_XXX_toBytes(&t[0],x); + FP_YYY_redc(x,&(f->a.a.a.b)); + BIG_XXX_toBytes(&t[MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->a.a.b.a)); + BIG_XXX_toBytes(&t[2*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->a.a.b.b)); + BIG_XXX_toBytes(&t[3*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->a.b.a.a)); + BIG_XXX_toBytes(&t[4*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->a.b.a.b)); + BIG_XXX_toBytes(&t[5*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->a.b.b.a)); + BIG_XXX_toBytes(&t[6*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->a.b.b.b)); + BIG_XXX_toBytes(&t[7*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->b.a.a.a)); + BIG_XXX_toBytes(&t[8*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->b.a.a.b)); + BIG_XXX_toBytes(&t[9*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->b.a.b.a)); + BIG_XXX_toBytes(&t[10*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->b.a.b.b)); + BIG_XXX_toBytes(&t[11*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->b.b.a.a)); + BIG_XXX_toBytes(&t[12*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->b.b.a.b)); + BIG_XXX_toBytes(&t[13*MODBYTES_XXX],x); + + FP_YYY_redc(x,&(f->b.b.b.a)); + BIG_XXX_toBytes(&t[14*MODBYTES_XXX],x); + FP_YYY_redc(x,&(f->b.b.b.b)); + BIG_XXX_toBytes(&t[15*MODBYTES_XXX],x); + + ECP_ZZZ_get(x,y,P); + BIG_XXX_toBytes(&t[16*MODBYTES_XXX],x); + BIG_XXX_toBytes(&t[17*MODBYTES_XXX],y); + + OCT_empty(w); + switch (sha) + { + case SHA256: + HASH256_init(&sha256); + for (i=0; i<18*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]); + HASH256_hash(&sha256,h); + break; + case SHA384: + HASH384_init(&sha512); + for (i=0; i<18*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]); + HASH384_hash(&sha512,h); + break; + case SHA512: + HASH512_init(&sha512); + for (i=0; i<18*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]); + HASH512_hash(&sha512,h); + break; + } + + OCT_jbytes(w,h,AESKEY_ZZZ); + for (i=0; i<hlen; i++) h[i]=0; +} + +/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* maps a random u to a point on the curve */ +static void map(ECP_ZZZ *P,BIG_XXX u,int cb) +{ + BIG_XXX x,q; + + BIG_XXX_rcopy(q,Modulus_YYY); + BIG_XXX_copy(x,u); + BIG_XXX_mod(x,q); + + while (!ECP_ZZZ_setx(P,x,cb)) + { + BIG_XXX_inc(x,1); BIG_XXX_norm(x); + } +} + +/* returns u derived from P. Random value in range 1 to return value should then be added to u */ +static int unmap(BIG_XXX u,int *cb,ECP_ZZZ *P) +{ + int s,r=0; + BIG_XXX x; + + s=ECP_ZZZ_get(x,x,P); + BIG_XXX_copy(u,x); + do + { + BIG_XXX_dec(u,1); BIG_XXX_norm(u); + r++; + } + while (!ECP_ZZZ_setx(P,u,s)); + ECP_ZZZ_setx(P,x,s); + + *cb=s; + + return r; +} + +/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */ +/* Note that u and v are indistinguisible from random strings */ +int MPIN_ZZZ_ENCODING(csprng *RNG,octet *E) +{ + int rn,m,su,sv,res=0; + + BIG_XXX q,u,v; + ECP_ZZZ P,W; + + if (!ECP_ZZZ_fromOctet(&P,E)) res=MPIN_INVALID_POINT; + if (res==0) + { + BIG_XXX_rcopy(q,Modulus_YYY); + + BIG_XXX_randomnum(u,q,RNG); + + su=RAND_byte(RNG); + if (su<0) su=-su; + su%=2; + map(&W,u,su); + ECP_ZZZ_sub(&P,&W); + + rn=unmap(v,&sv,&P); + m=RAND_byte(RNG); + if (m<0) m=-m; + m%=rn; + BIG_XXX_inc(v,m+1); + E->val[0]=su+2*sv; + BIG_XXX_toBytes(&(E->val[1]),u); + BIG_XXX_toBytes(&(E->val[PFS_ZZZ+1]),v); + } + return res; +} + +int MPIN_ZZZ_DECODING(octet *D) +{ + int su,sv; + BIG_XXX u,v; + ECP_ZZZ P,W; + int res=0; + + if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT; + if (res==0) + { + + BIG_XXX_fromBytes(u,&(D->val[1])); + BIG_XXX_fromBytes(v,&(D->val[PFS_ZZZ+1])); + + su=D->val[0]&1; + sv=(D->val[0]>>1)&1; + map(&W,u,su); + map(&P,v,sv); + ECP_ZZZ_add(&P,&W); + ECP_ZZZ_toOctet(D,&P,false); + } + + return res; +} + +/* R=R1+R2 in group G1 */ +int MPIN_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R) +{ + ECP_ZZZ P,T; + int res=0; + if (res==0) + { + if (!ECP_ZZZ_fromOctet(&P,R1)) res=MPIN_INVALID_POINT; + if (!ECP_ZZZ_fromOctet(&T,R2)) res=MPIN_INVALID_POINT; + } + if (res==0) + { + ECP_ZZZ_add(&P,&T); + ECP_ZZZ_toOctet(R,&P,false); + } + return res; +} + +/* W=W1+W2 in group G2 */ +int MPIN_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W) +{ + ECP8_ZZZ Q,T; + int res=0; + if (!ECP8_ZZZ_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT; + if (!ECP8_ZZZ_fromOctet(&T,W2)) res=MPIN_INVALID_POINT; + if (res==0) + { + ECP8_ZZZ_add(&Q,&T); + ECP8_ZZZ_toOctet(W,&Q); + } + return res; +} + +/* create random secret S */ +int MPIN_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S) +{ + BIG_XXX r,s; + + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + BIG_XXX_randomnum(s,r,RNG); +#ifdef AES_S + BIG_XXX_mod2m(s,2*AES_S); +#endif + BIG_XXX_toBytes(S->val,s); + S->len=MODBYTES_XXX; + return 0; +} + +/* Extract PIN from TOKEN for identity CID */ +int MPIN_ZZZ_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN) +{ + pin%=MAXPIN; + return MPIN_ZZZ_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN); +} + +/* Extract a factor < 32 bits for identity CID */ +int MPIN_ZZZ_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN) +{ + ECP_ZZZ P,R; + int res=0; + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + + if (!ECP_ZZZ_fromOctet(&P,TOKEN)) res=MPIN_INVALID_POINT; + if (res==0) + { + mhashit(sha,-1,CID,&H); + ECP_ZZZ_mapit(&R,&H); + + ECP_ZZZ_pinmul(&R,factor,facbits); + ECP_ZZZ_sub(&P,&R); + + ECP_ZZZ_toOctet(TOKEN,&P,false); + } + return res; +} + +/* Extract a factor < 32 bits for identity CID */ +int MPIN_ZZZ_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN) +{ + ECP_ZZZ P,R; + int res=0; + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + + if (!ECP_ZZZ_fromOctet(&P,TOKEN)) res=MPIN_INVALID_POINT; + if (res==0) + { + mhashit(sha,-1,CID,&H); + ECP_ZZZ_mapit(&R,&H); + + ECP_ZZZ_pinmul(&R,factor,facbits); + ECP_ZZZ_add(&P,&R); + + ECP_ZZZ_toOctet(TOKEN,&P,false); + } + return res; +} + +/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */ +int MPIN_ZZZ_CLIENT_2(octet *X,octet *Y,octet *SEC) +{ + BIG_XXX px,py,r; + ECP_ZZZ P; + int res=0; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + if (!ECP_ZZZ_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT; + if (res==0) + { + BIG_XXX_fromBytes(px,X->val); + BIG_XXX_fromBytes(py,Y->val); + BIG_XXX_add(px,px,py); + BIG_XXX_mod(px,r); + PAIR_ZZZ_G1mul(&P,px); + ECP_ZZZ_neg(&P); + ECP_ZZZ_toOctet(SEC,&P,false); + } + return res; +} + +/* + W=x*H(G); + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve +*/ + +int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W) +{ + ECP_ZZZ P; + BIG_XXX r,x; + int res=0; + if (RNG!=NULL) + { + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + BIG_XXX_randomnum(x,r,RNG); +#ifdef AES_S + BIG_XXX_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES_XXX; + BIG_XXX_toBytes(X->val,x); + } + else + BIG_XXX_fromBytes(x,X->val); + + if (type==0) + { + if (!ECP_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT; + } + else + { + ECP_ZZZ_mapit(&P,G); + } + + if (res==0) + { + PAIR_ZZZ_G1mul(&P,x); + ECP_ZZZ_toOctet(W,&P,false); + } + return res; +} + +/* + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + W=x*G where G is point on the curve + if type==1 W=(x^-1)G +*/ + +int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W) +{ + ECP8_ZZZ P; + BIG_XXX r,x; + int res=0; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + if (RNG!=NULL) + { + BIG_XXX_randomnum(x,r,RNG); +#ifdef AES_S + BIG_XXX_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES_XXX; + BIG_XXX_toBytes(X->val,x); + } + else + { + BIG_XXX_fromBytes(x,X->val); + if (type==1) BIG_XXX_invmodp(x,x,r); + } + + if (!ECP8_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT; + + if (res==0) + { + PAIR_ZZZ_G2mul(&P,x); + ECP8_ZZZ_toOctet(W,&P); + } + return res; +} + + + +/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */ +/* CID is hashed externally */ +int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST) +{ + return MPIN_ZZZ_GET_G1_MULTIPLE(NULL,1,S,CID,CST); +} + +/* Implement step 1 on client side of MPin protocol */ +int MPIN_ZZZ_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT) +{ + BIG_XXX r,x; + ECP_ZZZ P,T,W; + int res=0; + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + if (RNG!=NULL) + { + BIG_XXX_randomnum(x,r,RNG); +#ifdef AES_S + BIG_XXX_mod2m(x,2*AES_S); +#endif + X->len=MODBYTES_XXX; + BIG_XXX_toBytes(X->val,x); + } + else + BIG_XXX_fromBytes(x,X->val); + + mhashit(sha,-1,CLIENT_ID,&H); + + ECP_ZZZ_mapit(&P,&H); + + if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT; + + if (res==0) + { + pin%=MAXPIN; + + ECP_ZZZ_copy(&W,&P); // W=H(ID) + ECP_ZZZ_pinmul(&W,pin,PBLEN); // W=alpha.H(ID) + ECP_ZZZ_add(&T,&W); // T=Token+alpha.H(ID) = s.H(ID) + + if (date) + { + if (PERMIT!=NULL) + { + if (!ECP_ZZZ_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT; + ECP_ZZZ_add(&T,&W); // SEC=s.H(ID)+s.H(T|ID) + } + mhashit(sha,date,&H,&H); + + ECP_ZZZ_mapit(&W,&H); + if (xID!=NULL) + { + PAIR_ZZZ_G1mul(&P,x); // P=x.H(ID) + ECP_ZZZ_toOctet(xID,&P,false); // xID + PAIR_ZZZ_G1mul(&W,x); // W=x.H(T|ID) + ECP_ZZZ_add(&P,&W); + } + else + { + ECP_ZZZ_add(&P,&W); + PAIR_ZZZ_G1mul(&P,x); + } + if (xCID!=NULL) ECP_ZZZ_toOctet(xCID,&P,false); // U + } + else + { + if (xID!=NULL) + { + PAIR_ZZZ_G1mul(&P,x); // P=x.H(ID) + ECP_ZZZ_toOctet(xID,&P,false); // xID + } + } + } + + if (res==0) + { + ECP_ZZZ_toOctet(SEC,&T,false); // V + } + return res; +} + +/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ +int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SST) +{ + BIG_XXX r,s; + ECP8_ZZZ Q; + int res=0; + + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + ECP8_ZZZ_generator(&Q); + + if (res==0) + { + BIG_XXX_fromBytes(s,S->val); + PAIR_ZZZ_G2mul(&Q,s); + ECP8_ZZZ_toOctet(SST,&Q); + } + + return res; +} + + +/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */ +int MPIN_ZZZ_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT) +{ + BIG_XXX s; + ECP_ZZZ P; + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + + mhashit(sha,date,CID,&H); + + ECP_ZZZ_mapit(&P,&H); + + BIG_XXX_fromBytes(s,S->val); + + PAIR_ZZZ_G1mul(&P,s); + + ECP_ZZZ_toOctet(CTT,&P,false); + return 0; +} + +// if date=0 only use HID, set HCID=NULL +// if date and PE, use HID and HCID + +/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */ +void MPIN_ZZZ_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID) +{ + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + ECP_ZZZ P,R; + BIG_XXX x; + +#ifdef USE_ANONYMOUS + ECP_ZZZ_mapit(&P,CID); +#else + mhashit(sha,-1,CID,&H); + ECP_ZZZ_mapit(&P,&H); +#endif + + ECP_ZZZ_toOctet(HID,&P,false); // new + + if (date) + { +#ifdef USE_ANONYMOUS + mhashit(sha,date,CID,&H); +#else + mhashit(sha,date,&H,&H); +#endif + ECP_ZZZ_mapit(&R,&H); + ECP_ZZZ_add(&P,&R); + ECP_ZZZ_toOctet(HTID,&P,false); + } +} + +/* Implement M-Pin on server side */ +int MPIN_ZZZ_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa) +{ + BIG_XXX px,py,y; + FP48_YYY g; + ECP8_ZZZ Q,sQ; + ECP_ZZZ P,R; + int res=0; + + ECP8_ZZZ_generator(&Q); + + // key-escrow less scheme: use Pa instead of Q in pairing computation + // Q left for backward compatiblity + if (Pa!=NULL) + { + if (!ECP8_ZZZ_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT; + } + + + if (res==0) + { + if (!ECP8_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT; + } + + if (res==0) + { + if (date) + { + if (!ECP_ZZZ_fromOctet(&R,xCID)) res=MPIN_INVALID_POINT; + } + else + { + if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; + } + } + if (res==0) + { + BIG_XXX_fromBytes(y,Y->val); + if (date) + { + if (!ECP_ZZZ_fromOctet(&P,HTID)) res=MPIN_INVALID_POINT; + } + else + { + if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT; + } + } + if (res==0) + { + PAIR_ZZZ_G1mul(&P,y); // y(A+AT) + ECP_ZZZ_add(&P,&R); // x(A+AT)+y(A+T) + if (!ECP_ZZZ_fromOctet(&R,mSEC)) res=MPIN_INVALID_POINT; // V + } + if (res==0) + { + + PAIR_ZZZ_double_ate(&g,&Q,&R,&sQ,&P); + PAIR_ZZZ_fexp(&g); + + if (!FP48_YYY_isunity(&g)) + { + if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL) + { + /* xID is set to NULL if there is no way to calculate PIN error */ + FP48_YYY_toOctet(E,&g); + + /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */ + + if (date) + { + if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT; + if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U + + if (res==0) + { + PAIR_ZZZ_G1mul(&P,y); // yA + ECP_ZZZ_add(&P,&R); // yA+xA + } + } + if (res==0) + { + PAIR_ZZZ_ate(&g,&Q,&P); + PAIR_ZZZ_fexp(&g); + FP48_YYY_toOctet(F,&g); + } + } + res=MPIN_BAD_PIN; + } + } + + return res; +} + +#if MAXPIN==10000 +#define MR_TS 10 /* 2^10/10 approx = sqrt(MAXPIN) */ +#define TRAP 200 /* 2*sqrt(MAXPIN) */ +#endif + +#if MAXPIN==1000000 +#define MR_TS 14 +#define TRAP 2000 +#endif + +/* Pollards kangaroos used to return PIN error */ +int MPIN_ZZZ_KANGAROO(octet *E,octet *F) +{ + int i,j,m,s,dn,dm,steps; + int distance[MR_TS]; + FP48_YYY ge,gf,t,table[MR_TS]; + int res=0; + + FP48_YYY_fromOctet(&ge,E); + FP48_YYY_fromOctet(&gf,F); + + FP48_YYY_copy(&t,&gf); + + for (s=1,m=0; m<MR_TS; m++) + { + distance[m]=s; + FP48_YYY_copy(&table[m],&t); + s*=2; + FP48_YYY_usqr(&t,&t); + FP48_YYY_reduce(&t); + } + + FP48_YYY_one(&t); + + for (dn=0,j=0; j<TRAP; j++) + { + i=t.a.a.a.a.a.g[0]%MR_TS; + + FP48_YYY_mul(&t,&table[i]); + FP48_YYY_reduce(&t); + dn+=distance[i]; + } + + FP48_YYY_conj(&gf,&t); + steps=0; + dm=0; + while (dm-dn<MAXPIN) + { + steps++; + if (steps>4*TRAP) break; + i=ge.a.a.a.a.a.g[0]%MR_TS; + + FP48_YYY_mul(&ge,&table[i]); + FP48_YYY_reduce(&ge); + dm+=distance[i]; + if (FP48_YYY_equals(&ge,&t)) + { + res=dm-dn; + break; + } + if (FP48_YYY_equals(&ge,&gf)) + { + res=dn-dm; + break; + } + } + if (steps>4*TRAP || dm-dn>=MAXPIN) + { + res=0; /* Trap Failed - probable invalid token */ + } + + return res; +} + +/* Functions to support M-Pin Full */ + +int MPIN_ZZZ_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2) +{ + ECP_ZZZ P,T; + ECP8_ZZZ Q; + FP48_YYY g; + BIG_XXX x; + int res=0; + + if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT; + + if (res==0) + { + ECP_ZZZ_mapit(&P,CID); + if (CP!=NULL) + { + if (!ECP8_ZZZ_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT; + } + else + { + ECP8_ZZZ_generator(&Q); + } + } + if (res==0) + { + PAIR_ZZZ_ate(&g,&Q,&T); + PAIR_ZZZ_fexp(&g); + + FP48_YYY_toOctet(G1,&g); + if (G2!=NULL) + { + PAIR_ZZZ_ate(&g,&Q,&P); + PAIR_ZZZ_fexp(&g); + FP48_YYY_toOctet(G2,&g); + } + } + return res; +} + +/* calculate common key on client side */ +/* wCID = w.(A+AT) */ +int MPIN_ZZZ_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK) +{ + FP48_YYY g1,g2; + FP16_YYY c; + + ECP_ZZZ W; + int res=0; + BIG_XXX r,z,x,h; + + FP48_YYY_fromOctet(&g1,G1); + FP48_YYY_fromOctet(&g2,G2); + BIG_XXX_fromBytes(z,R->val); + BIG_XXX_fromBytes(x,X->val); + BIG_XXX_fromBytes(h,H->val); + + if (!ECP_ZZZ_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT; + + if (res==0) + { + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + BIG_XXX_add(z,z,h); // new + BIG_XXX_mod(z,r); + + FP48_YYY_pinpow(&g2,pin,PBLEN); + FP48_YYY_mul(&g1,&g2); + + PAIR_ZZZ_G1mul(&W,x); + + FP48_YYY_compow(&c,&g1,z,r); + mpin_hash(sha,&c,&W,CK); + + } + return res; +} + +/* calculate common key on server side */ +/* Z=r.A - no time permits involved */ + +int MPIN_ZZZ_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK) +{ + int res=0; + FP48_YYY g; + FP16_YYY c; + ECP_ZZZ R,U,A; + ECP8_ZZZ sQ; + BIG_XXX w,h; + + if (!ECP8_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT; + if (!ECP_ZZZ_fromOctet(&R,Z)) res=MPIN_INVALID_POINT; + + + if (!ECP_ZZZ_fromOctet(&A,HID)) res=MPIN_INVALID_POINT; + + // new + if (xCID!=NULL) + { + if (!ECP_ZZZ_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT; + } + else + { + if (!ECP_ZZZ_fromOctet(&U,xID)) res=MPIN_INVALID_POINT; + } + BIG_XXX_fromBytes(w,W->val); + BIG_XXX_fromBytes(h,H->val); + + + PAIR_ZZZ_ate(&g,&sQ,&A); + PAIR_ZZZ_fexp(&g); + + if (res==0) + { + PAIR_ZZZ_G1mul(&A,h); + ECP_ZZZ_add(&R,&A); // new + PAIR_ZZZ_ate(&g,&sQ,&R); + PAIR_ZZZ_fexp(&g); + PAIR_ZZZ_G1mul(&U,w); + FP48_YYY_trace(&c,&g); + mpin_hash(sha,&c,&U,SK); + } + return res; +} + +/* Generate Y = H(TimeValue, xCID/xID) */ +void MPIN_ZZZ_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y) +{ + BIG_XXX q,y; + char h[MODBYTES_XXX]; + octet H= {0,sizeof(h),h}; + + mhashit(sha,TimeValue,xCID,&H); + BIG_XXX_fromBytes(y,H.val); + BIG_XXX_rcopy(q,CURVE_Order_ZZZ); + BIG_XXX_mod(y,q); + BIG_XXX_toBytes(Y->val,y); + Y->len=PGS_ZZZ; +} + +/* One pass MPIN Client */ +int MPIN_ZZZ_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y) +{ + int rtn=0; + char m[M_SIZE_ZZZ]; + octet M= {0,sizeof(m),m}; + + octet *pID; + if (date == 0) + pID = U; + else + pID = UT; + + rtn = MPIN_ZZZ_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP); + if (rtn != 0) + return rtn; + + OCT_joctet(&M,pID); + if (MESSAGE!=NULL) + { + OCT_joctet(&M,MESSAGE); + } + + MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y); + + rtn = MPIN_ZZZ_CLIENT_2(X,Y,V); + if (rtn != 0) + return rtn; + + return 0; +} + +/* One pass MPIN Server */ +int MPIN_ZZZ_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa) +{ + int rtn=0; + char m[M_SIZE_ZZZ]; + octet M= {0,sizeof(m),m}; + + octet *pU; + if (date == 0) + pU = U; + else + pU = UT; + + MPIN_ZZZ_SERVER_1(sha,date,ID,HID,HTID); + + OCT_joctet(&M,pU); + if (MESSAGE!=NULL) + { + OCT_joctet(&M,MESSAGE); + } + + MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y); + + rtn = MPIN_ZZZ_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa); + if (rtn != 0) + return rtn; + + return 0; +} + +int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa) +{ + BIG_XXX z,r; + ECP8_ZZZ Q; + int res=0; + + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + if (R!=NULL) + { + BIG_XXX_randomnum(z,r,R); + Z->len=MODBYTES_XXX; + BIG_XXX_toBytes(Z->val,z); + } + else + BIG_XXX_fromBytes(z,Z->val); + + BIG_XXX_invmodp(z,z,r); + + ECP8_ZZZ_generator(&Q); + + if (res==0) + { + PAIR_ZZZ_G2mul(&Q,z); + ECP8_ZZZ_toOctet(Pa,&Q); + } + + return res; +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/mpin256.h ---------------------------------------------------------------------- diff --git a/version3/c/mpin256.h b/version3/c/mpin256.h new file mode 100644 index 0000000..46ba21a --- /dev/null +++ b/version3/c/mpin256.h @@ -0,0 +1,339 @@ +/* +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 mpin.h + * @author Mike Scott and Kealan McCusker + * @date 2nd June 2015 + * @brief M-Pin Header file + * + * Allows some user configuration + * defines structures + * declares functions + * + */ + +#ifndef MPIN_ZZZ_H +#define MPIN_ZZZ_H + +#include "pair256_ZZZ.h" +#include "pbc_support.h" + + +/* Field size is assumed to be greater than or equal to group size */ + +#define PGS_ZZZ MODBYTES_XXX /**< MPIN Group Size */ +#define PFS_ZZZ MODBYTES_XXX /**< MPIN Field Size */ + +#define MPIN_OK 0 /**< Function completed without error */ +#define MPIN_INVALID_POINT -14 /**< Point is NOT on the curve */ +#define MPIN_BAD_PIN -19 /**< Bad PIN number entered */ + +#define MAXPIN 10000 /**< max PIN */ +#define PBLEN 14 /**< max length of PIN in bits */ + +//#define PAS_ZZZ 24 /**< MPIN Symmetric Key Size 192 bits */ +//#define HASH_TYPE_MPIN_ZZZ SHA384 /**< Choose Hash function */ + +#define MESSAGE_SIZE 256 /**< Signature message size */ +#define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1) /**< Signature message size and G1 size */ + +/* MPIN support functions */ + +/* MPIN primitives */ + + +void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y); +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param factor is an input factor + @param facbits is the number of bits in the factor + @param CS is the client secret from which the factor is to be extracted + @return 0 or an error code + */ +int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS); + +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param factor is an input factor + @param facbits is the number of bits in the factor + @param CS is the client secret to which the factor is to be added + @return 0 or an error code + */ +int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS); + + +/** @brief Extract a PIN number from a client secret + * + @param h is the hash type + @param ID is the input client identity + @param pin is an input PIN number + @param CS is the client secret from which the PIN is to be extracted + @return 0 or an error code + */ +int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS); + +/** @brief Perform client side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y); +/** @brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input client identity + @param R is a pointer to a cryptographically secure random number generator + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param pin is the input PIN number + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit + @param U is output = x.H(ID) + @param UT is output = x.(H(ID)+H(d|H(ID))) + @param TP is the input time permit + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP); +/** @brief Generate a random group element + * + @param R is a pointer to a cryptographically secure random number generator + @param S is the output random octet + @return 0 or an error code + */ +int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S); +/** @brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol + * + @param x an input, a locally generated random number + @param y an input random challenge from the server + @param V on output = -(x+y).V + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V); +/** @brief Perform server side of the one-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @param y is output H(t|U) or H(t|UT) if Time Permits enabled + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param ID is the input claimed client identity + @param MESSAGE is the message to be signed + @param t is input epoch time in seconds - a timestamp + @param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa); +/** @brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol + * + @param h is the hash type + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param ID is the input claimed client identity + @param HID is output H(ID), a hash of the client ID + @param HTID is output H(ID)+H(d|H(ID)) + @return 0 or an error code + */ +void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID); +/** @brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol + * + If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL. + If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required. + @param d is input date, in days since the epoch. Set to 0 if Time permits disabled + @param HID is input H(ID), a hash of the client ID + @param HTID is input H(ID)+H(d|H(ID)) + @param y is the input server's randomly generated challenge + @param SS is the input server secret + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param V is an input from the client + @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required + @param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa); +/** @brief Add two members from the group G1 + * + @param Q1 an input member of G1 + @param Q2 an input member of G1 + @param Q an output member of G1 = Q1+Q2 + @return 0 or an error code + */ +int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q); +/** @brief Add two members from the group G2 + * + @param P1 an input member of G2 + @param P2 an input member of G2 + @param P an output member of G2 = P1+P2 + @return 0 or an error code + */ +int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P); +/** @brief Use Kangaroos to find PIN error + * + @param E a member of the group GT + @param F a member of the group GT = E^e + @return 0 if Kangaroos failed, or the PIN error e + */ +int MPIN_ZZZ_KANGAROO(octet *E,octet *F); +/** @brief Encoding of a Time Permit to make it indistinguishable from a random string + * + @param R is a pointer to a cryptographically secure random number generator + @param TP is the input time permit, obfuscated on output + @return 0 or an error code + */ +int MPIN_ZZZ_ENCODING(csprng *R,octet *TP); +/** @brief Encoding of an obfuscated Time Permit + * + @param TP is the input obfuscated time permit, restored on output + @return 0 or an error code + */ +int MPIN_ZZZ_DECODING(octet *TP); + +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to be taken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G if type=0 a point in G1, else an octet to be mapped to G1 + @param W the output =x.G or x.M(G), where M(.) is a mapping + @return 0 or an error code + */ +int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); +/** @brief Find a random multiple of a point in G1 + * + @param R is a pointer to a cryptographically secure random number generator + @param type determines type of action to betaken + @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input + @param G a point in G2 + @param W the output =x.G or (1/x).G + @return 0 or an error code + */ +int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W); + +/** @brief Create a client secret in G1 from a master secret and the client ID + * + @param S is an input master secret + @param ID is the input client identity + @param CS is the full client secret = s.H(ID) + @return 0 or an error code + */ +int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS); +/** @brief Create a Time Permit in G1 from a master secret and the client ID + * + @param h is the hash type + @param d is input date, in days since the epoch. + @param S is an input master secret + @param ID is the input client identity + @param TP is a Time Permit for the given date = s.H(d|H(ID)) + @return 0 or an error code + */ +int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP); +/** @brief Create a server secret in G2 from a master secret + * + @param S is an input master secret + @param SS is the server secret = s.Q where Q is a fixed generator of G2 + @return 0 or an error code + */ +int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS); +/* int MPIN_TEST_PAIRING(octet *,octet *); */ + +/* For M-Pin Full */ +/** @brief Precompute values for use by the client side of M-Pin Full + * + @param T is the input M-Pin token (the client secret with PIN portion removed) + @param ID is the input client identity + @param CP is Public Key (or NULL) + @param g1 precomputed output + @param g2 precomputed output + @return 0 or an error code + */ +int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2); +/** @brief Calculate Key on Server side for M-Pin Full + * + Uses UT internally for the key calculation, unless not available in which case U is used + @param h is the hash type + @param Z is the input Client-side Diffie-Hellman component + @param SS is the input server secret + @param w is an input random number generated by the server + @param p is an input, hash of the protocol transcript + @param I is the hashed input client ID = H(ID) + @param U is input from the client = x.H(ID) + @param UT is input from the client= x.(H(ID)+H(d|H(ID))) + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K); +/** @brief Calculate Key on Client side for M-Pin Full + * + @param h is the hash type + @param g1 precomputed input + @param g2 precomputed input + @param pin is the input PIN number + @param r is an input, a locally generated random number + @param x is an input, a locally generated random number + @param p is an input, hash of the protocol transcript + @param T is the input Server-side Diffie-Hellman component + @param K is the output calculated shared key + @return 0 or an error code + */ +int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K); + +/** @brief Generates a random public key for the client z.Q + * + @param R is a pointer to a cryptographically secure random number generator + @param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input + @param Pa the output public key for the client + */ +int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa); + +#endif + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/newhope.c ---------------------------------------------------------------------- diff --git a/version3/c/newhope.c b/version3/c/newhope.c new file mode 100644 index 0000000..0d02552 --- /dev/null +++ b/version3/c/newhope.c @@ -0,0 +1,510 @@ +/* +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. +*/ + +/* NewHope API implementation. Constant time. + + LOOK - no if statements! + + M.Scott 21/07/2017 +*/ + +#include "newhope.h" + +const sign16 roots[] ={0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x15 52,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284 d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fd d,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x 7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8, 0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24 b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf}; +const sign16 iroots[]= {0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5, 0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0 x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0 x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0x ce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2 466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af ,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f}; +const sign16 inv= 0xeab; +const sign16 invpr= 0x2c2a; + +#define DEGREE (1<<RLWE_LGN) +#define WL 32 + +#define round(a,b) (((a)+((b)/2))/(b)) + +/* constant time absolute vaue */ +static sign32 nabs(sign32 x) +{ + sign32 mask=(x>>31); + return (x+mask)^mask; +} + +/* Montgomery stuff */ + +static sign32 redc(unsign64 T) +{ + unsign32 m=(unsign32)T*(unsign32)RLWE_ND; + return ((unsign64)m*RLWE_PRIME+T)>>WL; +} + +static sign32 nres(unsign32 x) +{ + return redc((unsign64)x*RLWE_R2MODP); +} + +static sign32 modmul(unsign32 a,unsign32 b) +{ + return redc((unsign64)a*b); +} + +/* NTT code */ +/* Cooley-Tukey NTT */ + +static void ntt(sign32 *x) +{ + int m,i,j,k,t=DEGREE/2; + sign32 S,U,V,W,q=RLWE_PRIME; + +/* Convert to Montgomery form */ + for (j=0;j<DEGREE;j++) + x[j]=nres(x[j]); + + m=1; + while (m<DEGREE) + { + k=0; + for (i=0;i<m;i++) + { + S=roots[m+i]; + for (j=k;j<k+t;j++) + { + U=x[j]; + V=modmul(x[j+t],S); + x[j]=U+V; + x[j+t]=U+2*q-V; + } + k+=2*t; + } + t/=2; + m*=2; + } +} + +/* Gentleman-Sande INTT */ + +static void intt(sign32 *x) +{ + int m,i,j,k,t=1; + sign32 S,U,V,W,q=RLWE_PRIME; + + m=DEGREE/2; + while (m>1) + { + k=0; + for (i=0;i<m;i++) + { + S=iroots[m+i]; + for (j=k;j<k+t;j++) + { + U=x[j]; + V=x[j+t]; + x[j]=U+V; + W=U+DEGREE*q-V; + x[j+t]=modmul(W,S); + } + k+=2*t; + } + t*=2; + m/=2; + } + +/* Last iteration merged with n^-1 */ + + t=DEGREE/2; + for (j=0;j<t;j++) + { + U=x[j]; + V=x[j+t]; + W=U+DEGREE*q-V; + x[j+t]=modmul(W,(sign32)invpr); + x[j]=modmul(U+V,(sign32)inv); + } +/* convert back from Montgomery to "normal" form */ + for (j=0;j<DEGREE;j++) + { + x[j]=redc(x[j]); + x[j]-=q; + x[j]+=(x[j]>>(WL-1))&q; + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +static void NHSEncode(byte *key,sign32 *poly) +{ + int i,j,b,k,kj,q2; + + q2=RLWE_PRIME/2; + for (i=j=0;i<256;) + { + kj=key[j++]; + for (k=0;k<8;k++) + { + b=kj&1; + poly[i]=b*q2; + poly[i+256]=b*q2; + poly[i+512]=b*q2; + poly[i+768]=b*q2; + kj>>=1; + i++; + } + } +} + +static void NHSDecode(sign32 *poly,byte *key) +{ + int i,j,k; + sign32 b,t,q2; + q2=RLWE_PRIME/2; + for (i=0;i<32;i++) + key[i]=0; + + for (i=j=0;i<256;) + { + for (k=0;k<8;k++) + { + t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2); + + b=t-RLWE_PRIME; + b=(b>>31)&1; + key[j]=(key[j]>>1)+(b<<7); + i++; + } + j++; + } +} + +/* convert 32-byte seed to random polynomial */ + +static void parse(byte *seed,sign32 *poly) +{ + int i,j; + sign32 n; + byte hash[4*DEGREE]; + sha3 sh; + + SHA3_init(&sh,SHAKE128); + for (i=0;i<32;i++) + SHA3_process(&sh,seed[i]); + SHA3_shake(&sh,(char *)hash,4*DEGREE); + + for (i=j=0;i<DEGREE;i++) + { + + n=hash[j]&0x7f; n<<=8; + n+=hash[j+1]; n<<=8; + n+=hash[j+2]; n<<=8; + n+=hash[j+3]; j+=4; + poly[i]=nres(n); + } +} + +/* Compress 14 bits polynomial coefficients into byte array */ +/* 7 bytes is 3x14 */ + +static void NHSpack(sign32 *poly,byte *array) +{ + int i,j; + sign32 a,b,c,d; + + for (i=j=0;i<DEGREE; ) + { + a=poly[i++]; b=poly[i++]; c=poly[i++]; d=poly[i++]; + array[j++]=(byte)(a&0xff); + array[j++]=(byte)(((a>>8)|(b<<6))&0xff); + array[j++]=(byte)((b>>2)&0xff); + array[j++]=(byte)(((b>>10)|(c<<4))&0xff); + array[j++]=(byte)((c>>4)&0xff); + array[j++]=(byte)(((c>>12)|(d<<2))&0xff); + array[j++]=(byte)(d>>6); + } +} + +static void NHSunpack(byte *array,sign32 *poly) +{ + int i,j; + sign32 a,b,c,d,e,f,g; + + for (i=j=0;i<DEGREE; ) + { + a=((sign32)array[j++])&0xff; b=((sign32)array[j++])&0xff; c=((sign32)array[j++])&0xff; d=((sign32)array[j++])&0xff; e=((sign32)array[j++])&0xff; f=((sign32)array[j++])&0xff; g=((sign32)array[j++])&0xff; + poly[i++]=a|((b&0x3f)<<8); + poly[i++]=(b>>6)|(c<<2)|((d&0xf)<<10); + poly[i++]=(d>>4)|(e<<4)|((f&3)<<12); + poly[i++]=(f>>2)|(g<<6); + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +static void NHSCompress(sign32 *poly,byte *array) +{ + int i,j,k,b; + unsign32 col=0; + + for (i=j=0;i<DEGREE;) + { + for (k=0;k<8;k++) + { + b=round((poly[i]*8),RLWE_PRIME)&7; + col=(col<<3)+b; + i++; + } + array[j]=col&0xff; + array[j+1]=(col>>8)&0xff; + array[j+2]=(col>>16)&0xff; + j+=3; col=0; + } +} + +static void NHSDecompress(byte *array,sign32 *poly) +{ + int i,j,k,b; + unsign32 col=0; + + for (i=j=0;i<DEGREE;) + { + col=array[j+2]; + col=(col<<8)+array[j+1]; + col=(col<<8)+array[j]; + j+=3; + for (k=0;k<8;k++) + { + b=(col&0xe00000)>>21; col<<=3; + poly[i]=round((b*RLWE_PRIME),8); + i++; + } + } +} + +/* generate centered binomial distribution */ + +static void NHSError(csprng *RNG,sign32 *poly) +{ + int i,j; + sign32 n1,n2,r; + for (i=0;i<DEGREE;i++) + { + n1=RAND_byte(RNG)+(RAND_byte(RNG)<<8); + n2=RAND_byte(RNG)+(RAND_byte(RNG)<<8); + r=0; + for (j=0;j<16;j++) + { + r+=(n1&1)-(n2&1); + n1>>=1; n2>>=1; + } + poly[i]=(r+RLWE_PRIME); + } +} + +static void redc_it(sign32 *p) +{ + int i; + for (i=0;i<DEGREE;i++) + p[i]=redc(p[i]); +} + +static void nres_it(sign32 *p) +{ + int i; + for (i=0;i<DEGREE;i++) + p[i]=nres(p[i]); +} + +static void poly_mul(sign32 *p1,sign32 *p2,sign32 *p3) +{ + int i; + for (i=0;i<DEGREE;i++) + p1[i]=modmul(p2[i],p3[i]); +} + +static void poly_add(sign32 *p1,sign32 *p2,sign32 *p3) +{ + int i; + for (i=0;i<DEGREE;i++) + p1[i]=(p2[i]+p3[i]); +} + +static void poly_sub(sign32 *p1,sign32 *p2,sign32 *p3) +{ + int i; + for (i=0;i<DEGREE;i++) + p1[i]=(p2[i]+RLWE_PRIME-p3[i]); +} + +/* reduces inputs < 2q */ +static void poly_soft_reduce(sign32 *poly) +{ + int i; + sign32 e; + for (i=0;i<DEGREE;i++) + { + e=poly[i]-RLWE_PRIME; + poly[i]=e+((e>>(WL-1))&RLWE_PRIME); + } +} + +/* fully reduces modulo q */ +static void poly_hard_reduce(sign32 *poly) +{ + int i; + sign32 e; + for (i=0;i<DEGREE;i++) + { + e=modmul(poly[i],RLWE_ONE); + e=e-RLWE_PRIME; + poly[i]=e+((e>>(WL-1))&RLWE_PRIME); + } +} + +/* API files */ + +void NHS_SERVER_1(csprng *RNG,octet *SB,octet *S) +{ + int i; + byte seed[32],array[1792]; + sign32 s[DEGREE],e[DEGREE],b[DEGREE]; + + for (i=0;i<32;i++) + seed[i]=RAND_byte(RNG); + + parse(seed,b); + + NHSError(RNG,e); + NHSError(RNG,s); + + ntt(s); + ntt(e); + poly_mul(b,b,s); + poly_add(b,b,e); + poly_hard_reduce(b); + + redc_it(b); + NHSpack(b,array); + + OCT_empty(SB); + OCT_jbytes(SB,(char *)seed,32); + OCT_jbytes(SB,(char *)array,1792); + + poly_hard_reduce(s); + + NHSpack(s,array); + OCT_empty(S); + OCT_jbytes(S,(char *)array,1792); + +} + +void NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY) +{ + int i; + sha3 sh; + byte seed[32],array[1792],key[32],cc[384]; + sign32 sd[DEGREE],ed[DEGREE],u[DEGREE],k[DEGREE],c[DEGREE]; + NHSError(RNG,sd); + NHSError(RNG,ed); + + ntt(sd); + ntt(ed); + + for (i=0;i<32;i++) + seed[i]=SB->val[i]; + + for (i=0;i<1792;i++) + array[i]=SB->val[i+32]; + + parse(seed,u); + + poly_mul(u,u,sd); + poly_add(u,u,ed); + poly_hard_reduce(u); + + for (i=0;i<32;i++) + key[i]=RAND_byte(RNG); + + SHA3_init(&sh,SHA3_HASH256); + for (i=0;i<32;i++) + SHA3_process(&sh,key[i]); + SHA3_hash(&sh,(char *)key); + + NHSEncode(key,k); + + NHSunpack(array,c); + nres_it(c); + + poly_mul(c,c,sd); + intt(c); + NHSError(RNG,ed); + poly_add(c,c,ed); + poly_add(c,c,k); + + NHSCompress(c,cc); + + SHA3_init(&sh,SHA3_HASH256); + for (i=0;i<32;i++) + SHA3_process(&sh,key[i]); + SHA3_hash(&sh,(char *)key); + + OCT_empty(KEY); + OCT_jbytes(KEY,(char *)key,32); + + redc_it(u); + NHSpack(u,array); + + OCT_empty(UC); + OCT_jbytes(UC,(char *)array,1792); + OCT_jbytes(UC,(char *)cc,384); +} + +void NHS_SERVER_2(octet *S,octet *UC,octet *KEY) +{ + int i; + sha3 sh; + sign32 c[DEGREE],s[DEGREE],k[DEGREE]; + byte array[1792],key[32],cc[384]; + + for (i=0;i<1792;i++) + array[i]=UC->val[i]; + + NHSunpack(array,k); + nres_it(k); + + for (i=0;i<384;i++) + cc[i]=UC->val[i+1792]; + + NHSDecompress(cc,c); + + for (i=0;i<1792;i++) + array[i]=S->val[i]; + + NHSunpack(array,s); + + poly_mul(k,k,s); + intt(k); + poly_sub(k,c,k); + poly_soft_reduce(k); + + NHSDecode(k,key); + + SHA3_init(&sh,SHA3_HASH256); + for (i=0;i<32;i++) + SHA3_process(&sh,key[i]); + SHA3_hash(&sh,(char *)key); + + OCT_empty(KEY); + OCT_jbytes(KEY,(char *)key,32); +} + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/newhope.h ---------------------------------------------------------------------- diff --git a/version3/c/newhope.h b/version3/c/newhope.h new file mode 100644 index 0000000..8e18a9a --- /dev/null +++ b/version3/c/newhope.h @@ -0,0 +1,51 @@ +/* + 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. +*/ + +/* NewHope Simple API */ + +#ifndef NHS_H +#define NHS_H + +#include "amcl.h" + +/** @brief NHS server first pass + * + @param RNG Random Number Generator handle + @param SB seed and polynomial B concatenated - output + @param S server secret - output + + */ +extern void NHS_SERVER_1(csprng *RNG,octet *SB,octet *S); +/** @brief NHS client pass + * + @param RNG Random Number Generator handle + @param SB seed and polynomial B concatenated - input + @param UC polynomial U and compressed polynomial c - output + @param KEY client key + */ +extern void NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY); +/** @brief NHS server second pass + * + @param S server secret - input + @param UC polynomial U and compressed polynomial c - input + @param KEY server key + */ +extern void NHS_SERVER_2(octet *S,octet *UC,octet *KEY); + +#endif \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/oct.c ---------------------------------------------------------------------- diff --git a/version3/c/oct.c b/version3/c/oct.c new file mode 100644 index 0000000..866c96c --- /dev/null +++ b/version3/c/oct.c @@ -0,0 +1,401 @@ +/* +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. +*/ + +/*** Basic Octet string maintainance routines ***/ +/* SU=m, m is Stack Usage */ + +#include <string.h> +#include "amcl.h" + +/* Output an octet string (Debug Only) */ + +/* SU= 16 */ +/* output octet */ +void OCT_output(octet *w) +{ + int i; + unsigned char ch; + for (i=0; i<w->len; i++) + { + ch=w->val[i]; + printf("%02x",ch); + } + printf("\n"); +} + +/* SU= 16 */ +void OCT_output_string(octet *w) +{ + int i; + unsigned char ch; + for (i=0; i<w->len; i++) + { + ch=w->val[i]; + printf("%c",ch); + } + /* printf("\n"); */ +} + +/* Convert C string to octet format - truncates if no room */ +void OCT_jstring(octet *y,char *s) +{ + int i,j; + i=y->len; + j=0; + while (s[j]!=0 && i<y->max) + { + y->val[i]=s[j]; + y->len++; + i++; + j++; + } +} + +/* compare 2 octet strings. + * If x==y return TRUE, else return FALSE */ +/* SU= 8 */ +int OCT_comp(octet *x,octet *y) +{ + int i; + if (x->len>y->len) return 0; + if (x->len<y->len) return 0; + for (i=0; i<x->len; i++) + { + if (x->val[i]!=y->val[i]) return 0; + } + return 1; +} + +/* check are first n bytes the same (in constant time) */ + +int OCT_ncomp(octet *x,octet *y,int n) +{ + int i,res=0; + if (n>y->len || n>x->len) return 0; + for (i=0; i<n; i++) + { + res|=(int)(x->val[i]^y->val[i]); + } + if (res==0) return 1; + return 0; +} + +/* Shift octet to the left by n bytes. Leftmost bytes disappear */ +void OCT_shl(octet *x,int n) +{ + int i; + if (n>=x->len) + { + x->len=0; + return; + } + x->len-=n; + for (i=0; i<x->len; i++) + x->val[i]=x->val[i+n]; +} + +/* Append binary string to octet - truncates if no room */ +/* SU= 12 */ +void OCT_jbytes(octet *y,char *b,int len) +{ + int i,j; + i=y->len; + for (j=0; j<len && i<y->max; j++) + { + y->val[i]=b[j]; + y->len++; + i++; + } +} + +/* Concatenates two octet strings */ +/* SU= 8 */ +void OCT_joctet(octet *y,octet *x) +{ + /* y=y || x */ + int i,j; + if (x==NULL) return; + + for (i=0; i<x->len; i++) + { + j=y->len+i; + if (j>=y->max) + { + y->len=y->max; + return; + } + y->val[j]=x->val[i]; + } + y->len+=x->len; +} + +/* Append byte to octet rep times */ +/* SU= 8 */ +void OCT_jbyte(octet *y,int ch,int rep) +{ + int i,j; + i=y->len; + for (j=0; j<rep && i<y->max; j++) + { + y->val[i]=ch; + y->len++; + i++; + } +} + +/* XOR common bytes of x with y */ +/* SU= 8 */ +void OCT_xor(octet *y,octet *x) +{ + /* xor first x->len bytes of y */ + + int i; + for (i=0; i<x->len && i<y->len; i++) + { + y->val[i]^=x->val[i]; + } +} + +/* clear an octet */ +void OCT_empty(octet *w) +{ + w->len=0; +} + +/* Kill an octet string - Zeroise it for security */ +void OCT_clear(octet *w) +{ + int i; + for (i=0; i<w->max; i++) w->val[i]=0; + w->len=0; +} + +/* appends int x of length len bytes to OCTET string */ +/* SU= 8 */ +void OCT_jint(octet *y,int x,int len) +{ + int i,n; + n=y->len+len; + if (n>y->max || len<=0) return; + for (i=y->len; i<n; i++) y->val[i]=0; + y->len=n; + + i=y->len; + while (x>0 && i>0) + { + i--; + y->val[i]=x%256; + x/=256; + } +} + +/* Pad an octet to a given length */ +/* SU= 8 */ +int OCT_pad(octet *w,int n) +{ + int i,d; + if (w->len>n || n>w->max) return 0; + if (n==w->len) return 1; + d=n-w->len; + for (i=n-1; i>=d; i--) + w->val[i]=w->val[i-d]; + for (i=d-1; i>=0; i--) + w->val[i]=0; + w->len=n; + return 1; +} + + +/* Convert an octet string to base64 string */ +/* SU= 56 */ +void OCT_tobase64(char *b,octet *w) +{ + int i,j,k,rem,last; + int c,ch[4]; + unsigned char ptr[3]; + rem=w->len%3; + j=k=0; + last=4; + while (j<w->len) + { + for (i=0; i<3; i++) + { + if (j<w->len) ptr[i]=w->val[j++]; + else + { + ptr[i]=0; + last--; + } + } + ch[0]=(ptr[0]>>2)&0x3f; + ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f; + ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f; + ch[3]=ptr[2]&0x3f; + for (i=0; i<last; i++) + { + c=ch[i]; + if (c<26) c+=65; + if (c>=26 && c<52) c+=71; + if (c>=52 && c<62) c-=4; + if (c==62) c='+'; + if (c==63) c='/'; + b[k++]=c; + } + } + if (rem>0) for (i=rem; i<3; i++) b[k++]='='; + b[k]='\0'; /* dangerous! */ +} + +/* SU= 56 */ +void OCT_frombase64(octet *w,char *b) +{ + int i,j,k,pads,len=(int)strlen(b); + int c,ch[4],ptr[3]; + j=k=0; + while (j<len && k<w->max) + { + pads=0; + for (i=0; i<4; i++) + { + c=80+b[j++]; + if (c<=112) continue; /* ignore white space */ + if (c>144 && c<171) c-=145; + if (c>176 && c<203) c-=151; + if (c>127 && c<138) c-=76; + if (c==123) c=62; + if (c==127) c=63; + if (c==141) + { + pads++; /* ignore pads '=' */ + continue; + } + ch[i]=c; + } + ptr[0]=(ch[0]<<2)|(ch[1]>>4); + ptr[1]=(ch[1]<<4)|(ch[2]>>2); + ptr[2]=(ch[2]<<6)|ch[3]; + for (i=0; i<3-pads && k<w->max; i++) + { + /* don't put in leading zeros */ + w->val[k++]=ptr[i]; + } + } + w->len=k; +} + +/* copy an octet string - truncates if no room */ +/* SU= 16 */ +void OCT_copy(octet *y,octet *x) +{ + int i; + OCT_clear(y); + y->len=x->len; + if (y->len>y->max) y->len=y->max; + + for (i=0; i<y->len; i++) + y->val[i]=x->val[i]; +} + +/* XOR m with all of x */ +void OCT_xorbyte(octet *x,int m) +{ + int i; + for (i=0; i<x->len; i++) x->val[i]^=m; +} + +/* truncates x to n bytes and places the rest in y (if y is not NULL) */ +/* SU= 8 */ +void OCT_chop(octet *x,octet *y,int n) +{ + int i; + if (n>=x->len) + { + if (y!=NULL) y->len=0; + return; + } + if (y!=NULL) y->len=x->len-n; + x->len=n; + + if (y!=NULL) + { + for (i=0; i<y->len && i<y->max; i++) y->val[i]=x->val[i+n]; + } +} + +/* set x to len random bytes */ +void OCT_rand(octet *x,csprng *RNG,int len) +{ + int i; + if (len>x->max) len=x->max; + x->len=len; + + for (i=0; i<len; i++) x->val[i]=RAND_byte(RNG); +} + +/* Convert an octet to a hex string */ +void OCT_toHex(octet *src,char *dst) +{ + int i; + unsigned char ch; + for (i=0; i<src->len; i++) + { + ch=src->val[i]; + sprintf(&dst[i*2],"%02x", ch); + } +} + +static int char2int(char input) +{ + if(input >= '0' && input <= '9') + return input - '0'; + if(input >= 'A' && input <= 'F') + return input - 'A' + 10; + if(input >= 'a' && input <= 'f') + return input - 'a' + 10; + return 0; +} + +/* Convert from a hex string */ +void OCT_fromHex(octet *dst,char *src) +{ + int i=0; + int j=0; + OCT_clear(dst); + + while(src[j]!=0) + { + dst->val[i++] = char2int(src[j])*16 + char2int(src[j+1]); + j += 2; + } + dst->len=i; +} + + +/* Convert an octet to a string */ +void OCT_toStr(octet *src,char *dst) +{ + int i; + unsigned char ch; + for (i=0; i<src->len; i++) + { + ch=src->val[i]; + sprintf(&dst[i],"%c", ch); + } +} +
