diff -uNr a/smg_comms/c_wrappers/README b/smg_comms/c_wrappers/README --- a/smg_comms/c_wrappers/README false +++ b/smg_comms/c_wrappers/README fb1426a00c38f5c9d94c79071cfd6e8d39343efec1fea43b771f8c96ca53e075339a28a2c2d7ab1a2d42b1ae128e0090f4dc580477f211680742cfd027c958fe @@ -0,0 +1,4 @@ + --Set of wrapper methods for C code to be easily imported and used from Ada. + --Meant to be the ONLY C lib that Ada code directly imports, an interface. + --Methods use arrays of octets (char*) and do all and any of the C-mess ops. + --S.MG, 2018 diff -uNr a/smg_comms/c_wrappers/bin/README b/smg_comms/c_wrappers/bin/README --- a/smg_comms/c_wrappers/bin/README false +++ b/smg_comms/c_wrappers/bin/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/c_wrappers/c_wrappers.c b/smg_comms/c_wrappers/c_wrappers.c --- a/smg_comms/c_wrappers/c_wrappers.c false +++ b/smg_comms/c_wrappers/c_wrappers.c 0bd7662525269421638c3cf0b5013c4e89b3181be9d081fd6ce4cac5afd731ae831eeae39f854bcbd5d31a134c47d1083f3c92a44f6ddf64d6160de04e4d561c @@ -0,0 +1,222 @@ +//Wrapper methods for C implementations of RSA and MPI. +//To be used / called from Ada so that the C part remains well separated. +//S.MG, 2018 + +#include "c_wrappers.h" +#include "mpi.h" +#include "smg_rsa.h" +#include +#include //for memmove... + +//Wrapper for comparing the given arrays of octets as MPIs +//Steps: +//1. allocate space for 2 MPIs u and v +//2. set buffer of u to content of a, buffer of v to content of b +//3. call mpi_cmp(u,v) and store result +//4. de-allocate u and v +//5. return result +int mpi_cmp_octets(char *a, unsigned int len_a, char *b, unsigned int len_b) { + //variable to hold the final result of comparing a to b as MPIs + int result; + + //calculate how much space is needed for each MPI + unsigned int nlimbs_a = mpi_nlimb_hint_from_nbytes( len_a ); + unsigned int nlimbs_b = mpi_nlimb_hint_from_nbytes( len_b ); + + //allocate space for the 2 MPIs + MPI u = mpi_alloc(nlimbs_a); + MPI v = mpi_alloc(nlimbs_b); + + //set the given octets as the values of the 2 MPIs + //the sign is set to 0 (last parameter). + mpi_set_buffer(u, a, len_a, 0); + mpi_set_buffer(v, b, len_b, 0); + + //compare the MPIs as numbers and store the result + result = mpi_cmp(u, v); + + //tidy up: free the memory allocated for the 2 MPIs + mpi_free(u); + mpi_free(v); + + //return the result comparing a to b as MPIs + return result; +} + +//Encryption of given input with a public RSA key: n and e given as octets too. +//Steps: +//1. create (allocate memory for) MPIs for out and input; +//2. set the input as buffer for the corresponding MPI; +//3. create and set the public key structure with n,e as contents; +//4. call rsa/public_rsa and retrieve the result storing it in out; +//5. free allocated memory for all the MPIs. +//6. return the actual length of the encrypted result +int public_rsa_octets( char *out , unsigned int len_out, + char *input, unsigned int len_input, + char *n , unsigned int len_n, + char *e , unsigned int len_e) { + + // precondition: output has enough memory allocated + assert( len_out >= KEY_LENGTH_OCTETS ); + + //allocate memory for input and output MPIs + unsigned int nlimbs_in = mpi_nlimb_hint_from_nbytes( len_input ); + unsigned int nlimbs_out = mpi_nlimb_hint_from_nbytes( len_out ); + MPI in_mpi = mpi_alloc(nlimbs_in); + MPI out_mpi = mpi_alloc(nlimbs_out); + + //set input as buffer for in_mpi + mpi_set_buffer(in_mpi, input, len_input, 0); + + //create public key structure and set its contents to given n, e + RSA_public_key pk; + unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( len_n ); + unsigned int nlimbs_e = mpi_nlimb_hint_from_nbytes( len_e ); + pk.n = mpi_alloc(nlimbs_n); + pk.e = mpi_alloc(nlimbs_e); + mpi_set_buffer(pk.n, n, len_n, 0); + mpi_set_buffer(pk.e, e, len_e, 0); + + //call rsa public_key encryption and retrieve the result, storing it in out + public_rsa( out_mpi, in_mpi, &pk); + int len = len_out; + mpi_to_octets( out, &len, out_mpi ); + + //tidy up: free allocated memory for ALL MPIs. + mpi_free(in_mpi); + mpi_free(out_mpi); + mpi_free(pk.n); + mpi_free(pk.e); + + //return actual length + return len; +} + +//Decryption of given input with the private key given through its components. +//Steps: +//1. create (allocate memory for) MPIs for out and input; +//2. set the input as buffer for the corresponding MPI; +//3. create and set the private key structure with n,e,d,p,q,u as contents; +//4. call rsa/private_rsa and retrieve the result storing it in out; +//5. free allocated memory for all the MPIs. +//6. return the actual length of the result +int private_rsa_octets( char *out, unsigned int len_out, + char *input, unsigned int len_input, + char *n , unsigned int len_n, + char *e , unsigned int len_e, + char *d , unsigned int len_d, + char *p , unsigned int len_p, + char *q , unsigned int len_q, + char *u , unsigned int len_u) { + // precondition: output has enough memory allocated + assert( len_out >= KEY_LENGTH_OCTETS ); + + //allocate memory for input and output MPIs + unsigned int nlimbs_in = mpi_nlimb_hint_from_nbytes( len_input ); + unsigned int nlimbs_out = mpi_nlimb_hint_from_nbytes( len_out ); + MPI in_mpi = mpi_alloc(nlimbs_in); + MPI out_mpi = mpi_alloc(nlimbs_out); + + //set input as buffer for in_mpi + mpi_set_buffer(in_mpi, input, len_input, 0); + + //create private key structure and set its contents to given n,e,d,p,q,u + RSA_secret_key sk; + unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( len_n ); + unsigned int nlimbs_e = mpi_nlimb_hint_from_nbytes( len_e ); + unsigned int nlimbs_d = mpi_nlimb_hint_from_nbytes( len_d ); + unsigned int nlimbs_p = mpi_nlimb_hint_from_nbytes( len_p ); + unsigned int nlimbs_q = mpi_nlimb_hint_from_nbytes( len_q ); + unsigned int nlimbs_u = mpi_nlimb_hint_from_nbytes( len_u ); + sk.n = mpi_alloc(nlimbs_n); + sk.e = mpi_alloc(nlimbs_e); + sk.d = mpi_alloc(nlimbs_d); + sk.p = mpi_alloc(nlimbs_p); + sk.q = mpi_alloc(nlimbs_q); + sk.u = mpi_alloc(nlimbs_u); + mpi_set_buffer(sk.n, n, len_n, 0); + mpi_set_buffer(sk.e, e, len_e, 0); + mpi_set_buffer(sk.d, d, len_d, 0); + mpi_set_buffer(sk.p, p, len_p, 0); + mpi_set_buffer(sk.q, q, len_q, 0); + mpi_set_buffer(sk.u, u, len_u, 0); + + //call rsa secret_key encryption and retrieve the result, storing it in out + secret_rsa( out_mpi, in_mpi, &sk ); + int len = len_out; + mpi_to_octets( out, &len, out_mpi ); + + //tidy up: free memory previously allocated for MPIs + mpi_free(in_mpi); + mpi_free(out_mpi); + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); + + //return number of octets copied in out - real length of result + return len; +} + +//Generates a new RSA key and stores its components at the specified locations. +void gen_rsa_octets( char *n, unsigned int *len_n, + char *e, unsigned int *len_e, + char *d, unsigned int *len_d, + char *p, unsigned int *len_p, + char *q, unsigned int *len_q, + char *u, unsigned int *len_u) { + // precondition: all pointers have enough memory allocated + assert( *len_n >= KEY_LENGTH_OCTETS ); + assert( *len_e >= KEY_LENGTH_OCTETS ); + assert( *len_d >= KEY_LENGTH_OCTETS ); + assert( *len_p >= KEY_LENGTH_OCTETS / 2); + assert( *len_q >= KEY_LENGTH_OCTETS / 2); + assert( *len_u >= KEY_LENGTH_OCTETS / 2); + + //the secret key structure that will hold generated key components + RSA_secret_key sk; + int nlimbs = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS ); + int nlimbs_pq = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS / 2 ); + + sk.n = mpi_alloc(nlimbs); + sk.e = mpi_alloc(nlimbs); + sk.d = mpi_alloc(nlimbs); + sk.p = mpi_alloc(nlimbs_pq); + sk.q = mpi_alloc(nlimbs_pq); + sk.u = mpi_alloc(nlimbs_pq); + + //generate the rsa key pair - this may take a while! + gen_keypair(&sk); + + //copy components to their place + mpi_to_octets( n, len_n, sk.n ); + mpi_to_octets( e, len_e, sk.e ); + mpi_to_octets( d, len_d, sk.d ); + mpi_to_octets( p, len_p, sk.p ); + mpi_to_octets( q, len_q, sk.q ); + mpi_to_octets( u, len_u, sk.u ); + + //tidy up: free ALL MPIs + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); +} + +void mpi_to_octets( char *out, unsigned int *len_out, MPI m) { + //copy the components as raw octets to the given pointers + int len = 0; + int sign; + unsigned char * buffer = mpi_get_buffer( m, &len, &sign ); + + //check and don't copy MORE than there is allocated space in out! + assert( len <= *len_out ); + memmove( out, buffer, len ); + *len_out = len; //save actual length of the component + + xfree( buffer ); //free the buffer that was allocated by mpi_get_buffer +} diff -uNr a/smg_comms/c_wrappers/c_wrappers.gpr b/smg_comms/c_wrappers/c_wrappers.gpr --- a/smg_comms/c_wrappers/c_wrappers.gpr false +++ b/smg_comms/c_wrappers/c_wrappers.gpr ce32037651dc139757805b3f6b25b73a47015ea87b9d17995f59cf8c0fa856e2d74d552a043da7d931f579656a9cac3e4366a0f9feda6c2f3b9f61e0166c3a24 @@ -0,0 +1,16 @@ +-- S.MG, 2018 + +with "../mpi/mpi.gpr"; +with "../rsa/rsa.gpr"; + +project C_Wrappers is + for Languages use ("C"); + for Library_Name use "C_Wrappers"; + for Library_Kind use "static"; + + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Library_Dir use "bin"; + +end C_Wrappers; + diff -uNr a/smg_comms/c_wrappers/c_wrappers.h b/smg_comms/c_wrappers/c_wrappers.h --- a/smg_comms/c_wrappers/c_wrappers.h false +++ b/smg_comms/c_wrappers/c_wrappers.h c24569926e5388672b1af9e79b01b55902f2176de3f2887c978327871820cf1ee19bc9b0b52ba614a90ff197fac4a91c0975133ec55b38f362be48e3deace1b3 @@ -0,0 +1,105 @@ +//Wrapper methods for C implementations of RSA and MPI. +//To be used / called from Ada so that the C part remains well separated and +// can therefore be swapped easily at a later stage for something sane. +//S.MG, 2018 + +#include "mpi.h" + +//Comparison of 2 arrays of octets interpreted as MPIs. +//This method creates 2 MPIs out of the given arrays of octes and then +// calls the mpi_cmp method from mpi/mpi-cmp.c, returning its result. +// ************************************************************************ +// ***NB: Make SURE that a and b have indeed allocated at least len_a and +// ***** len_b octets respectively! NO CHECKS PERFORMED BY THIS METHOD! +// ************************************************************************ +//@param a An array of octets representing the first MPI. +//@param len_a The length of the first array (number of octets). +//@param b An array of octets representing the second MPI. +//@param len_b The length of the second array (number of octets). +//@return 0 when a=b, -1 when ab +int mpi_cmp_octets(char *a, unsigned int len_a, char *b, unsigned int len_b); + +//Encryption of given octets with public RSA key: n and e given as octets too. +// ************************************************************************ +// ***Length of output is KEY_LENGTH_OCTETS. +// ***NB: Make SURE that out, input, n and e have enough space allocated!! +// ***NB: NO MEMORY ALLOCATED for its parameters by this method and +// ***** NO CHECKS PERFORMED BY THIS METHOD! +// ************************************************************************ +//@param out Pointer to ALREADY ALLOCATED space for the encrypted data. +//@param len_out Length of the allocated space for out (in octets). +//@param input Pointer to the data to be encrypted. +//@param len_input Length of the allocated space for input (in octets). +//@param n Pointer to the public RSA modulus to use for encryption. +//@param len_n Length of n (in octets). +//@param e Pointer to the public RSA exponent to use for encryption. +//@param len_e Length of e (in octets). +//@return The actual length of the output i.e. number of chars written to out. +int public_rsa_octets( char *out , unsigned int len_out, + char *input, unsigned int len_input, + char *n , unsigned int len_n, + char *e , unsigned int len_e); + + +//Encryption of given octets with *private* RSA key given as octets. +// ************************************************************************ +// ***Length of output is KEY_LENGTH_OCTETS. +// ***NB: Make SURE that ALL pointers have enough space allocated!! +// ***NB: NO MEMORY ALLOCATED for its parameters by this method and +// ***** NO CHECKS PERFORMED BY THIS METHOD! +// ************************************************************************ +//@param out Pointer to ALREADY ALLOCATED space for the encrypted data. +//@param len_out Length of the allocated space for out (in octets). +//@param input Pointer to the data to be encrypted. +//@param len_input Length of the allocated space for input (in octets). +//@param n Pointer to the public RSA modulus of the given key. +//@param len_n Length of n (in octets). +//@param e Pointer to the public RSA exponent of the given key. +//@param len_e Length of e (in octets). +//@param d Pointer to the private RSA exponent of the given key. +//@param len_d Length of d (in octets). +//@param p Pointer to the prime p of the given key. +//@param len_p Length of p (in octets). +//@param q Pointer to the prime q of the given key. +//@param len_q Length of q (in octets). +//@param u Pointer to the inverse of p mod q for the given key. +//@param len_u Length of u (in octets). +//@return The actual length of the output i.e. number of chars written to out. +int private_rsa_octets( char *out, unsigned int len_out, + char *input, unsigned int len_input, + char *n , unsigned int len_n, + char *e , unsigned int len_e, + char *d , unsigned int len_d, + char *p , unsigned int len_p, + char *q , unsigned int len_q, + char *u , unsigned int len_u); + +//Generates a new RSA key and stores its components at the specified locations. +//@param n Pointer to the public RSA modulus of the given key. +//@param len_n Length of n (in octets). +//@param e Pointer to the public RSA exponent of the given key. +//@param len_e Length of e (in octets). +//@param d Pointer to the private RSA exponent of the given key. +//@param len_d Length of d (in octets). +//@param p Pointer to the prime p of the given key. +//@param len_p Length of p (in octets). +//@param q Pointer to the prime q of the given key. +//@param len_q Length of q (in octets). +//@param u Pointer to the inverse of p mod q for the given key. +//@param len_u Length of u (in octets). +void gen_rsa_octets( char *n, unsigned int *len_n, + char *e, unsigned int *len_e, + char *d, unsigned int *len_d, + char *p, unsigned int *len_p, + char *q, unsigned int *len_q, + char *u, unsigned int *len_u); + +//Copies the buffer of m to the location to which out points. +//***************************************************************** +//*** This method does NOT allocate memory for out! +//*** NB: caller should allocate enough memory! +//***************************************************************** +//@param out pointer to allocated memory where to copy the MPI's octets +//@param len_out size of out; will be replaced by actual number of octets copied +//@param m The MPI whose octets are to be retrieved +void mpi_to_octets( char *out, unsigned int *len_out, MPI m); diff -uNr a/smg_comms/c_wrappers/obj/README b/smg_comms/c_wrappers/obj/README --- a/smg_comms/c_wrappers/obj/README false +++ b/smg_comms/c_wrappers/obj/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/c_wrappers/tests/c_wrappers_tests.gpr b/smg_comms/c_wrappers/tests/c_wrappers_tests.gpr --- a/smg_comms/c_wrappers/tests/c_wrappers_tests.gpr false +++ b/smg_comms/c_wrappers/tests/c_wrappers_tests.gpr 579bd4807f3de9e8a399e942e2401053b5d89a049c257491011456e2ed35d746e190fd642493fd76e8d803d2529eb9f39cad7bdf0e88ae5ab2cd0638c1a7ec13 @@ -0,0 +1,14 @@ + --Tests for the C wrappers on mpi and rsa methods. + --S.MG, 2018 + +with "../c_wrappers.gpr"; + +project C_Wrappers_Tests is + for Languages use("C"); + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Exec_Dir use "."; + + for Main use ("tests.c"); +end C_Wrappers_Tests; + diff -uNr a/smg_comms/c_wrappers/tests/obj/README b/smg_comms/c_wrappers/tests/obj/README --- a/smg_comms/c_wrappers/tests/obj/README false +++ b/smg_comms/c_wrappers/tests/obj/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/c_wrappers/tests/tests.c b/smg_comms/c_wrappers/tests/tests.c --- a/smg_comms/c_wrappers/tests/tests.c false +++ b/smg_comms/c_wrappers/tests/tests.c c40e451a3093c41c8c5762c284a1e05716c2e429ee7e56c1e93bb2adbff0d83fdba237dc01510891a362eecbf9c908501468a3747c4a735ff90d407504abe1f8 @@ -0,0 +1,352 @@ +//Basic tests for the C wrappers for rsa and mpi. +//S.MG, 2018 + +#include "mpi.h" +#include "smg_rsa.h" + +#include "c_wrappers.h" + +void test_mpi_cmp() { + int result; + int i; + char a[KEY_LENGTH_OCTETS]; + char b[KEY_LENGTH_OCTETS]; + + //initialize mpis + for (i=0;i b + a[240] = 241; + result = mpi_cmp_octets(a, KEY_LENGTH_OCTETS, b, KEY_LENGTH_OCTETS); + if (result == 1) + printf("PASS: mpi_cmp_octets on a > b.\n"); + else { + printf("FAIL: mpi_cmp_octets on a > b "); + printf("returned %d instead of 1.\n", result); + } +} + +void test_gen_rsa_octets() { + RSA_secret_key sk; + RSA_public_key pk; + int nlimbs = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS ); + int nlimbs_pq = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS / 2 ); + + //allocate memory + sk.n = mpi_alloc(nlimbs); + sk.e = mpi_alloc(nlimbs); + sk.d = mpi_alloc(nlimbs); + sk.p = mpi_alloc(nlimbs_pq); + sk.q = mpi_alloc(nlimbs_pq); + sk.u = mpi_alloc(nlimbs_pq); + + pk.n = mpi_alloc(nlimbs); + pk.e = mpi_alloc(nlimbs); + + //generate key pair + int len_n = KEY_LENGTH_OCTETS; + int len_e = len_n; + int len_d = len_n; + int len_p = KEY_LENGTH_OCTETS / 2; + int len_q = len_p; + int len_u = len_p; + char n[KEY_LENGTH_OCTETS]; + char e[KEY_LENGTH_OCTETS]; + char d[KEY_LENGTH_OCTETS]; + char p[KEY_LENGTH_OCTETS / 2]; + char q[KEY_LENGTH_OCTETS / 2]; + char u[KEY_LENGTH_OCTETS / 2]; + gen_rsa_octets(n, &len_n, + e, &len_e, + d, &len_d, + p, &len_p, + q, &len_q, + u, &len_u); + + //check encryption/decr works + mpi_set_buffer(sk.n, n, len_n, 0); + mpi_set_buffer(sk.e, e, len_e, 0); + mpi_set_buffer(sk.d, d, len_d, 0); + mpi_set_buffer(sk.p, p, len_p, 0); + mpi_set_buffer(sk.q, q, len_q, 0); + mpi_set_buffer(sk.u, u, len_u, 0); + + mpi_set_buffer(pk.n, n, len_n, 0); + mpi_set_buffer(pk.e, e, len_e, 0); + + MPI encr = mpi_alloc(0); + MPI plain = mpi_alloc(0); + MPI out = mpi_alloc(0); + mpi_fromstr(plain, "0x\ +5B6A8A0ACF4F4DB3F82EAC2D20255E4DF3E4B7C799603210766F26EF87C8980E737579\ +EC08E6505A51D19654C26D806BAF1B62F9C032E0B13D02AF99F7313BFCFD68DA46836E\ +CA529D7360948550F982C6476C054A97FD01635AB44BFBDBE2A90BE06F7984AC8534C3\ +28097EF92F6E78CAE0CB97"); + public_rsa(encr, plain, &pk); + secret_rsa(out, encr, &sk); + + if (mpi_cmp(out, plain) != 0) + printf("FAIL: test_gen_rsa encr/decr failed.\n"); + else + printf("PASS: test_gen_rsa encr/decr passed.\n"); + + //tidy up + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); + + mpi_free(pk.n); + mpi_free(pk.e); + + mpi_free(plain); + mpi_free(encr); + mpi_free(out); +} + +void test_rsa_octets() { + int noctets = 512; + RSA_public_key pk; + pk.n = mpi_alloc(0); + pk.e = mpi_alloc(0); + + RSA_secret_key sk; + sk.n = mpi_alloc(0); + sk.e = mpi_alloc(0); + sk.d = mpi_alloc(0); + sk.p = mpi_alloc(0); + sk.q = mpi_alloc(0); + sk.u = mpi_alloc(0); + +//key pair previously generated with EuCrypt + mpi_fromstr(sk.n, "0x\ +CD2C025323BEA46FFF2FA8D7A9D39817EA713421F4AE03FA8120641193892A70BFECF5\ +83101635A432110D3DDE6339E3CC7ECC0AD91C026FCACE832DD3888A6FCA7BCE56C390\ +5A5AC8C7BC921DA675E4B62489B254EB34659D547D71165BC998983A81937BD251AEE1\ +2D985EC387D5376F5DCC5EF7EC530FBD6FD2AA7285EE1AF3335EA73163F0954F30402E\ +D7B374EE84A97B1849B0674B0DA0A2050BD79B71ABB1559F3A9CFDB8557DED7BC90CF2\ +09E8A847E9C226140845B7D03842162E7DA5DD16326CB1F71A248D841FE9076A09911F\ +2F4F5E3EA44EA8DE40332BF00406990BCCF61C322A03C456EF3A98B341E0BDBC1088CE\ +683E78510E76B72C2BCC1EE9AEDD80FFF18ABFC5923B2F36B581C25114AB2DF9F6C2B1\ +9481703FD19E313DCD7ACE15FA11B27D25BCE5388C180A7E21167FB87750599E1ED7C7\ +50F4A844E1DC2270C62D19671CF8F4C25B81E366B09FC850AE642136D204A9160AEECE\ +575B57378AA439E9DD46DC990288CD54BAA35EEE1C02456CD39458A6F1CBF012DCEDF4\ +27CCF3F3F53645658FC49C9C9D7F2856DB571D92B967AB5845514E0054DDB49099F5DD\ +04A6F6F5C5CE642276834B932881AEB648D1F25E9223971F56E249EF40CF7D80F22621\ +CDD0260E9E7D23746960ADB52CF2987584FB1DE95A69A39E5CB12B76E0F5C1A0529C0C\ +065D2E35720810F7C7983180B9A9EA0E00C11B79DC3D"); + + mpi_fromstr(sk.e, "0x\ +DD4856B4EE3D099A8604AE392D8EFEC094CDF01546A28BE87CB484F999E8E75CDFCD01\ +D04D455A6A9254C60BD28C0B03611FC3E751CC27EF768C0B401C4FD2B27C092834A6F2\ +49A145C4EDC47A3B3D363EC352462C945334D160AF9AA72202862912493AC6190AA3A6\ +149D4D8B9996BA7927D3D0D2AD00D30FD630CF464E6CAF9CF49355B9A70E05DB7AE915\ +F9F602772F8D11E5FCDFC7709210F248052615967090CC1F43D410C83724AA5912B2F0\ +52E6B39449A89A97C79C92DC8CB8DEEFCF248C1E1D2FC5BFE85165ECA31839CAA9CEB3\ +3A92EBDC0EB3BAC0F810938BB173C7DA21DCBB2220D44CBA0FD40A2C868FC93AC5243E\ +C137C27B0A76D65634EBB3"); + + mpi_fromstr(sk.d, "0x\ +7C8A6FA1199D99DCA45E9BDF567CA49D02B237340D7E999150BC4883AE29DEC5158521\ +B338F35DC883792356BDDBB3C8B3030A6DD4C6522599A3254E751F9BA1CB1061C5633C\ +81BBFACF6FCD64502614102DFED3F3FA284066C342D5E00953B415915331E30812E5FB\ +CD6680ADCCDEE40B8376A3A225F2E160EA59C7566804526D73BB660A648A3EF9802313\ +B2F841E8458B2AAACE7AACF31083E8F3F630298138393BC88BBD7D4AA4334949651D25\ +365B10DBF4A4A08E20A6CC74BFDD37C1C38E2ADC2A283DF06590DF06B46F67F6ACA67F\ +AC464C795261659A2F9558802D0BBAA05FD1E1AF2CDC70654723DF7EFAEA148B8CDBEB\ +C89EA2320AB9BBB1BC4311475DF3D91446F02EF192368DFEBAC598CCFD4407DEC58FDC\ +1A94CCDD6E5FBA9C52164ACEA8AEE633E557BCCEACB7A1AF656C379482D784A120A725\ +32F9B2B35173D505F21D5AD4CB9511BC836DC923730B70291B70290A216CA3B21CFF79\ +E895C35F4F7AF80E1BD9ED2773BD26919A76E4298D169160593E0335BE2A2A2D2E8516\ +948F657E1B1260E18808A9D463C108535FB60B3B28F711C81E5DE24F40214134A53CE5\ +9A952C8970A1D771EBEFFA2F4359DCF157995B3F1950DE3C6EC41B7FF837148F55F323\ +372AF3F20CE8B8038E750C23D8F5041FA951327859B0E47483F0A47103EF808C72C251\ +006FA526245291C8C84C12D2EF63FB2301EA3EEDA42B"); + + mpi_fromstr(sk.p, "0x\ +E236732452039C14EC1D3B8095BDDCFB7625CE27B1EA5394CF4ED09D3CEECAA4FC0BF6\ +2F7CE975E0C8929CE84B0259D773EA038396479BF15DA065BA70E549B248D77B4B23ED\ +A267308510DBEE2FD44E35D880EE7CFB81E0646AA8630165BD8988C3A8776D9E704C20\ +AA25CA0A3C32F27F592D5FD363B04DD57D8C61FFDCDFCCC59E2913DE0EE47769180340\ +E1EA5A803AA2301A010FF553A380F002601F0853FCACDB82D76FE2FACBCD6E5F294439\ +0799EA5AE9D7880D4E1D4AE146DC1D4E8495B9DD30E57E883923C5FC26682B7142D35C\ +D8A0FC561FE725A6CF419B15341F40FE0C31132CBD81DD8E50697BD1EBFFA16B522E16\ +F5B49A03B707218C7DA60B"); + + mpi_fromstr(sk.q, "0x\ +E830482A3C4F5C3A7E59C10FF8BA760DB1C6D55880B796FFDA4A82E0B60E974E81D04B\ +2A4AD417823EBFB4E8EFB13782943562B19B6C4A680E3BA0C8E37B5023470F4F1AC1F8\ +A0B10672EF75CD58BCD45E6B14503B8A6A70AFE79F6201AF56E7364A1C742BE1453FD2\ +24FDC9D66522EAF4466A084BCB9E46D455A2946E94CBF028770F38D0B741C2CC59308F\ +71D8C2B4B9C928E0AE8D68DEB48A3E9EFD84A10301EBD55F8221CA32FC567B306B2A8E\ +116350AFB995859FDF4378C5CFD06901494E8CFA5D8FAC564D6531FA8A2E4761F5EFBA\ +F78750B6F4662BE9EA4C2FAD67AF73EEB36B41FC15CB678810C19A51DF23555695C4C1\ +546F3FACA39CAA7BB8DBD7"); + + mpi_fromstr(sk.u, "0x\ +846232322775C1CD7D5569DC59E2F3E61A885AE2E9C4A4F8CB3ACBE8C3A5441E5FE348\ +A2A8AC9C2998FBF282222BF508AA1ECF66A76AEDD2D9C97028BFD3F6CA0542E38A5312\ +603C70B95650CE73F80FDD729988FBDB5595A5BF8A007EA34E54994A697906CE56354C\ +E00DF10EB711DEC274A62494E3D350D88736CF67A477FB600AC9F1D6580727585092BF\ +5EBC092CC4D6CF75769051033A1197103BE269942F372168A53771746FBA18ED6972D5\ +0B935A9B1D6B5B3DD50CD89A27FE93C10924E9103FACF7B4C5724A046C3D3B50CC1C78\ +5F5C8E00DBE1D6561F120F5294C170914BC10F978ED4356EED67A9F3A60D70AFE540FC\ +5373CBAE3D0A7FD1C87273"); + +// copy the public key components + pk.n = mpi_copy( sk.n ); + pk.e = mpi_copy( sk.e ); + +// some plain text message + MPI plain = mpi_alloc(0); + mpi_fromstr(plain, "0x\ +5B6A8A0ACF4F4DB3F82EAC2D20255E4DF3E4B7C799603210766F26EF87C8980E737579\ +EC08E6505A51D19654C26D806BAF1B62F9C032E0B13D02AF99F7313BFCFD68DA46836E\ +CA529D7360948550F982C6476C054A97FD01635AB44BFBDBE2A90BE06F7984AC8534C3\ +28097EF92F6E78CAE0CB97"); + +// expected encrypted MPI (via rsa.c directly) + MPI encr = mpi_alloc(0); + public_rsa( encr, plain, &pk); + MPI decr = mpi_alloc(0); + secret_rsa( decr, encr, &sk); + if (mpi_cmp(decr, plain) != 0) + printf("FAIL: decrypted != plain in test_rsa_octets (MPI call)\n"); + +//allocate the char arrays for _octets rsa + int len_n = noctets; + int len_e = len_n; + int len_d = len_n; + int len_p = noctets / 2; + int len_q = len_p; + int len_u = len_p; + char n[noctets]; + char e[noctets]; + char d[noctets]; + char p[noctets / 2]; + char q[noctets / 2]; + char u[noctets / 2]; + +//copy the key components into char arrays + mpi_to_octets(n, &len_n, sk.n); + mpi_to_octets(e, &len_e, sk.e); + mpi_to_octets(d, &len_d, sk.d); + mpi_to_octets(p, &len_p, sk.p); + mpi_to_octets(q, &len_q, sk.q); + mpi_to_octets(u, &len_u, sk.u); + +//call _octets rsa and check results + int len_encr = noctets; + int len_decr = noctets; + int len_plain = noctets; + char plain_o[noctets]; + char encr_o[noctets]; + char expected_encr_o[noctets]; + char decr_o[noctets]; + char expected_decr_o[noctets]; + + mpi_to_octets(plain_o, &len_plain, plain); + mpi_to_octets(expected_encr_o, &len_encr, encr); + mpi_to_octets(expected_decr_o, &len_decr, decr); + len_decr = noctets; + + int len; + len = public_rsa_octets( encr_o, len_encr, plain_o, len_plain, + n, len_n, e, len_e); + if (len != len_encr) + printf("FAIL: actual len of encr is %d; expected %d\n", len, len_encr); + else + printf("PASS: actual len of encr matches expected: %d\n", len); + int errors= 0; + int i; + for (i=0;i0) + printf("FAIL: found %d errors in public_rsa_octets output\n", errors); + else + printf("PASS: no errors found in public_rsa_octets output\n"); + + len_encr = len; + len = private_rsa_octets( decr_o, len_decr, encr_o, len_encr, + n, len_n, e, len_e, + d, len_d, p, len_p, + q, len_q, u, len_u); + if (len != len_plain) + printf("FAIL: actual len of decr is %d; expected %d\n", len, len_plain); + else + printf("PASS: actual len of decr matches expected: %d\n", len); + + errors = 0; + for (i=0;i0) + printf("FAIL: found %d errors in private_rsa_octets output\n", errors); + else printf("PASS: no errors found in private_rsa_octets_output\n"); + + //tidy up + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); + + mpi_free(pk.n); + mpi_free(pk.e); + + mpi_free(plain); + mpi_free(encr); + mpi_free(decr); +} + +int main(int ac, char **av) { + if (ac < 2) { + printf("Usage: %s testID\n", av[0]); + return -1; + } + + int id = atoi(av[1]); + switch (id) { + case 1: + test_mpi_cmp(); + break; + case 2: + test_gen_rsa_octets(); + break; + case 3: + test_rsa_octets(); + break; + default: + printf("Current test ids:\n"); + printf("1 test of mpi_cmp_octets\n"); + printf("2 test of gen_rsa_octets (can be very SLOW!)\n"); + printf("3 test of rsa_octets (can take a few minutes)\n"); + } + return 0; +} diff -uNr a/smg_comms/manifest b/smg_comms/manifest --- a/smg_comms/manifest 84f1562e913676358d1bf1a9e6013f92bd61c79e2215eba0b19959f7166cfdc8a0a73e1e6139b9a467ad060a0f2d243b788986aff361167ffc7db5cdeb1fb15e +++ b/smg_comms/manifest 1d5b032f775b2b59d4bcbafdde81d65efb3e11925c30962717565cd0cb2c2218434dae770c470dc0a11b70f70b4cd78d37a3534741cfccb2e002cf4ed4e94008 @@ -1,3 +1,4 @@ 532398 smg_comms_genesis diana_coman The first seed of an implementation of S.MG's communication protocol for Eulora: definitions for basic types, methods to/from network format, basic client/server test running locally on the same machine. 546000 smg_comms_raw_types diana_coman Part of layer 0 - raw types for the updated version of the protocol containing only two types of packets: 1470 octets RSA packet and 1472 octets Serpent packet. 546152 smg_comms_packing_serpent diana_coman Packing/Unpacking Serpent messages <-> Serpent packets. Includes Serpent implementation. +547275 smg_comms_c_wrappers diana_coman C wrappers for RSA and MPI methods that are needed by SMG Comms (so that they can be called from Ada using only arrays of octets as inputs/outputs). diff -uNr a/smg_comms/mpi/COPYING b/smg_comms/mpi/COPYING --- a/smg_comms/mpi/COPYING false +++ b/smg_comms/mpi/COPYING 5b77e0898b3b6d0e202c38e9a85da30c6920c748463247e5ed6f1efc92c6794ce23ecbb83cdaed5cc79bffbf197c171b1de7fb872491b7a34966e1fb4d0e0d0f @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff -uNr a/smg_comms/mpi/README b/smg_comms/mpi/README --- a/smg_comms/mpi/README false +++ b/smg_comms/mpi/README 65a8797e0181e25a392820473f105126ffd8c5dd0fa57011d04ff984e852f7e338ee6fbda3c5fa176f1021b404e4712005aa9fc4d25041d924611f09d539074a @@ -0,0 +1,89 @@ +NB: this is used by the smg_rsa component of EuCrypt. + +What you see here is a very classic version of the GNU MPI (bignum) library. +It has been surgically removed from GnuPG 1.4.10, specifically as found at: + +http://trilema.com/wp-content/uploads/2015/10/gnupg-1.4.10.tar.gz.asc + +SHA512(gnupg-1.4.10.tar.gz) : +d037041d2e6882fd3b999500b5a7b42be2c224836afc358e1f8a2465c1b74473d518f185b7c324b2c8dec4ffb70e9e34a03c94d1a54cc55d297f40c9745f6e1b + +Recommended compilation: +1) gprbuild mpi.gpr + +Tests: +2) cd tests +3) gprbuild +4) ./test_mpi +5) output is: + 37A063D056817668C7AA3418F29 +6) q: 'Waaaaaa, it barfed!' + a: You are probably using GCC 5 or LLVM. Stop. + + +CHANGES FROM ORIGINAL: + +1) Everything pertaining to Automake was nuked, and the earth where it stood - + salted. + + Instead, we now have a conventional Makefile. It builds precisely + ONE THING - a single 'mpi.a' library suitable for static linking into + another project. This will turn up in 'bin'. + + Among other things, this now means that all KNOBS now reside in a + MANUALLY-controlled 'knobs.h' found in 'include'. If you are building + on some very peculiar unix, please read it and adjust as appropriate. + It contains ONLY those knobs which actually pertain to the code. + + The Makefile contains a 'check-syntax' - users of Emacs and Flymake + will see proper error-highlighting. + +2) ALL chip-specific ASM optimizations (including those found in longlong.h) + have been nuked. + +3) GPG-specific cruft has been amputated to the extent practical. + + The logging system has been retained, but it can be easily torn out, + which I may choose to do in the near future. + + The I/O buffering system has been retained. I may choose to remove it + in the near future. + + The 'secure memory' (unpageable alloc) system has been retained. + + 'Localization' and all related idiocies have been nuked. + Write hieroglyphs at home, leave them there, civilized folk + don't need'em in their source code. + +4) Other code has been altered solely to the extent required by items + (1), (2), and (3). + + Cruft which appears in dead #ifdefs may be removed in the future. + Don't get comfortable with it being there. + +5) Readers who wish to know EXACTLY what I changed, should get a copy of the + original tarball and write a simple script involving 'find' and 'vdiff', + which sadly did not fit in the margins of this page. + +6) To use the library, include 'include/mpi.h' in your project, + and statically link with 'bin/mpi.a'. + +7) The original code was distributed under GPL 3, which may apply on + your planet and is therefore included. (See COPYING.) + +---------- +UPDATE #1: +---------- + +1) Abolished the logging subsystem inherited from GPG. + +2) Abolished the I/O buffering subsystem, from same. + +3) Eliminated all #ifdef blocks pertaining to RiscOS. + +4) config.h is now knobs.h and is considerably shorter + on account of there now being a great many fewer knobs. + +5) Eliminated certain blocks of dead code. + +6) Inserted notice of modifications as specified in GPL-3 diff -uNr a/smg_comms/mpi/bin/README b/smg_comms/mpi/bin/README --- a/smg_comms/mpi/bin/README false +++ b/smg_comms/mpi/bin/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/mpi/include/knobs.h b/smg_comms/mpi/include/knobs.h --- a/smg_comms/mpi/include/knobs.h false +++ b/smg_comms/mpi/include/knobs.h 1e58d3eca9c3cc986a0b371f931498784570bbaecb5dcf98e85f159c2e7fff90ccb30063da8ca10f6d9d6c9e25deeace497436496e3d48ef4ae49f364d02182c @@ -0,0 +1,75 @@ +/* knobs.h -- Originally generated from config.h.in by autoconf. + * But there is no more autoconf in this project. + * + * No Such Labs. (C) 2015. See README. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#ifndef GNUPG_CONFIG_H_INCLUDED +#define GNUPG_CONFIG_H_INCLUDED + +/* Report memory usage. */ +//#define M_DEBUG 1 + +/* Define to 1 if you have the `atexit' function. */ +#define HAVE_ATEXIT 1 + +/* Defined if the mlock() call does not work */ +/* #undef HAVE_BROKEN_MLOCK */ + +/* Defined if a `byte' is typedef'd */ +/* #undef HAVE_BYTE_TYPEDEF */ + +/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) + with special properties like no file modes */ +/* #undef HAVE_DOSISH_SYSTEM */ + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Defined if the system supports an mlock() call */ +#define HAVE_MLOCK 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `plock' function. */ +/* #undef HAVE_PLOCK */ + +/* Define to 1 if you have the `raise' function. */ +#define HAVE_RAISE 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Defined if a `u16' is typedef'd */ +/* #undef HAVE_U16_TYPEDEF */ + +/* Defined if a `u32' is typedef'd */ +/* #undef HAVE_U32_TYPEDEF */ + +/* Defined if a `ulong' is typedef'd */ +#define HAVE_ULONG_TYPEDEF 1 + +/* Defined if a `ushort' is typedef'd */ +#define HAVE_USHORT_TYPEDEF 1 + +#endif /*GNUPG_CONFIG_H_INCLUDED*/ diff -uNr a/smg_comms/mpi/include/longlong.h b/smg_comms/mpi/include/longlong.h --- a/smg_comms/mpi/include/longlong.h false +++ b/smg_comms/mpi/include/longlong.h 0418e5bde9c91ccf99bc408f3088aa1ef37c3f8318ebc3babc9d9ab283a2ed3b158f0057ed885b0c336c69c4f58ac1ff4721d9188072dec45391c0f2cca7b250 @@ -0,0 +1,226 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/*************************************** + *********** Generic Versions ******** + ***************************************/ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char __clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff -uNr a/smg_comms/mpi/include/memory.h b/smg_comms/mpi/include/memory.h --- a/smg_comms/mpi/include/memory.h false +++ b/smg_comms/mpi/include/memory.h 27c0bd5775f26059d615f270d9e74c36e5c55f72fba1a95de0e15f66de1eec857e8470aa62bde31cba19024f80a3cf8e8b487582703f142b3c167eb02b0a0e86 @@ -0,0 +1,103 @@ +/* memory.h - memory allocation + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_MEMORY_H +#define G10_MEMORY_H + +#ifdef M_DEBUG + +#ifndef STR +#define STR(v) #v +#endif + +#define M_DBGINFO(a) __FUNCTION__ "["__FILE__ ":" STR(a) "]" + +#define xmalloc(n) m_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +#define xtrymalloc(n) m_debug_trymalloc ((n), M_DBGINFO( __LINE__ )) +#define xmalloc_clear(n) m_debug_alloc_clear((n), M_DBGINFO(__LINE__) ) +#define xmalloc_secure(n) m_debug_alloc_secure(n), M_DBGINFO(__LINE__) ) +#define xmalloc_secure_clear(n) m_debug_alloc_secure_clear((n), M_DBGINFO(__LINE__) ) +#define xrealloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) ) +#define xfree(n) m_debug_free((n), M_DBGINFO(__LINE__) ) +#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) ) +/*#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )*/ +#define xstrdup(a) m_debug_strdup((a), M_DBGINFO(__LINE__) ) +#define xtrystrdup(a) m_debug_trystrdup((a), M_DBGINFO(__LINE__) ) + +void *m_debug_alloc( size_t n, const char *info ); +void *m_debug_trymalloc (size_t n, const char *info); +void *m_debug_alloc_clear( size_t n, const char *info ); +void *m_debug_alloc_secure( size_t n, const char *info ); +void *m_debug_alloc_secure_clear( size_t n, const char *info ); +void *m_debug_realloc( void *a, size_t n, const char *info ); +void m_debug_free( void *p, const char *info ); +void m_debug_check( const void *a, const char *info ); +/*void *m_debug_copy( const void *a, const char *info );*/ +char *m_debug_strdup( const char *a, const char *info ); +char *m_debug_trystrdup (const char *a, const char *info); + +#else +void *xmalloc( size_t n ); +void *xtrymalloc (size_t n); +void *xmalloc_clear( size_t n ); +void *xmalloc_secure( size_t n ); +void *xmalloc_secure_clear( size_t n ); +void *xrealloc( void *a, size_t n ); +void xfree( void *p ); +void m_check( const void *a ); +/*void *m_copy( const void *a );*/ +char *xstrdup( const char * a); +char *xtrystrdup (const char *a); +#endif + +size_t m_size( const void *a ); +void m_print_stats(const char *prefix); + +/* The follwing functions should be preferred over xmalloc_clear. */ +void *xcalloc (size_t n, size_t m); +void *xcalloc_secure (size_t n, size_t m); + + +/*-- secmem.c --*/ +int secmem_init( size_t npool ); +void secmem_term( void ); +void *secmem_malloc( size_t size ); +void *secmexrealloc( void *a, size_t newsize ); +void secmem_free( void *a ); +int m_is_secure( const void *p ); +void secmem_dump_stats(void); +void secmem_set_flags( unsigned flags ); +unsigned secmem_get_flags(void); + + +#define DBG_MEMORY memory_debug_mode +#define DBG_MEMSTAT memory_stat_debug_mode + +#ifndef EXTERN_UNLESS_MAIN_MODULE +#define EXTERN_UNLESS_MAIN_MODULE +#endif +EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode; +EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; + + + +#endif /*G10_MEMORY_H*/ diff -uNr a/smg_comms/mpi/include/mpi-inline.h b/smg_comms/mpi/include/mpi-inline.h --- a/smg_comms/mpi/include/mpi-inline.h false +++ b/smg_comms/mpi/include/mpi-inline.h 2ea77d3e9c3d040649368883bdcaeca474685ef6968e358cdd744647292902e584e34949caba771cb43145f3ac1fce64932cf2e7d48ad514b84ee81fe5492c58 @@ -0,0 +1,121 @@ +/* mpi-inline.h - Internal to the Multi Precision Integers + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_MPI_INLINE_H +#define G10_MPI_INLINE_H + +#ifndef G10_MPI_INLINE_DECL +#define G10_MPI_INLINE_DECL extern __inline__ +#endif + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb += x; + *res_ptr++ = s2_limb; + if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ + while( --s1_size ) { + x = *s1_ptr++ + 1; /* add carry */ + *res_ptr++ = x; /* and store */ + if( x ) /* not 0 (no overflow): we can stop */ + goto leave; + } + return 1; /* return carry (size of s1 to small) */ + } + + leave: + if( res_ptr != s1_ptr ) { /* not the same variable */ + mpi_size_t i; /* copy the rest */ + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; /* no carry */ +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); + + if( s1_size - s2_size ) + cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if( s2_limb > x ) { + while( --s1_size ) { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if( x ) + goto leave; + } + return 1; + } + + leave: + if( res_ptr != s1_ptr ) { + mpi_size_t i; + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); + + if( s1_size - s2_size ) + cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + +#endif /*G10_MPI_INLINE_H*/ diff -uNr a/smg_comms/mpi/include/mpi-internal.h b/smg_comms/mpi/include/mpi-internal.h --- a/smg_comms/mpi/include/mpi-internal.h false +++ b/smg_comms/mpi/include/mpi-internal.h 0ec90eeed7bb58e2d737fddaf5cd8101cfb114c9d0824457384e5c199b4e1a75f1762bcd465cd4b675fe19da36197ee9bff0d3e24ed6b9e4c26a1a05ffc7386e @@ -0,0 +1,287 @@ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Modified by No Such Labs. (C) 2015. See README. + * Modified by S.MG, 2017: fixing broken MPN_COPY_INCR macro. See EuCrypt patches. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_MPI_INTERNAL_H +#define G10_MPI_INTERNAL_H + +#include "mpi.h" + +/* from the old mpi-asm-defs.h */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) + + +struct gcry_mpi { + int alloced; /* array size (# of allocated limbs) */ + int nlimbs; /* number of valid limbs */ + unsigned int nbits; /* the real number of valid bits (info only) */ + int sign; /* indicates a negative number */ + unsigned flags; /* bit 0: array must be allocated in secure memory space */ + /* bit 1: not used */ + /* bit 2: the limb is a pointer to some xmalloced data */ + mpi_limb_t *d; /* array with the limbs */ +}; + + + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + * value which is good on most machines. */ + +/* tested 4, 16, 32 and 64, where 16 gave the best performance when + * checking a 768 and a 1024 bit ElGamal signature. + * (wk 22.12.97) */ +#ifndef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 16 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 +#undef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 2 +#endif + + +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ +typedef int mpi_size_t; /* (must be a signed type) */ + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define RESIZE_IF_NEEDED(a,b) \ + do { \ + if( (a)->alloced < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) + +/* Copy N limbs from S to D. */ +#define MPN_COPY( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +#define MPN_COPY_INCR( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while (0) + +#define MPN_COPY_DECR( d, s, n ) \ + do { \ + mpi_size_t _i; \ + for( _i = (n)-1; _i >= 0; _i--) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +/* Zero N limbs at D */ +#define MPN_ZERO(d, n) \ + do { \ + int _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(d, n) \ + do { \ + while( (n) > 0 ) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_NORMALIZE_NOT_ZERO(d, n) \ + do { \ + for(;;) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + * If this would yield overflow, DI should be the largest possible number + * (i.e., only ones). For correct operation, the most significant bit of D + * has to be set. Put the quotient in Q and the remainder in R. + */ +#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ + do { \ + mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if( _xh ) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + if( _xh) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + } \ + } \ + if( _r >= (d) ) { \ + _r -= (d); \ + _q++; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) + + +/*-- mpiutil.c --*/ +#ifdef M_DEBUG +#define mpi_alloc_limb_space(n,f) mpi_debug_alloc_limb_space((n),(f), M_DBGINFO( __LINE__ ) ) +#define mpi_free_limb_space(n) mpi_debug_free_limb_space((n), M_DBGINFO( __LINE__ ) ) + mpi_ptr_t mpi_debug_alloc_limb_space( unsigned nlimbs, int sec, const char *info ); + void mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ); +#else + mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs, int sec ); + void mpi_free_limb_space( mpi_ptr_t a ); +#endif +void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ); + +/*-- mpi-bit.c --*/ +void mpi_rshift_limbs( MPI a, unsigned int count ); +void mpi_lshift_limbs( MPI a, unsigned int count ); + + +/*-- mpihelp-add.c --*/ +mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-sub.c --*/ +mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-cmp.c --*/ +int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); + +/*-- mpihelp-mul.c --*/ + +struct karatsuba_ctx { + struct karatsuba_ctx *next; + mpi_ptr_t tspace; + mpi_size_t tspace_size; + mpi_ptr_t tp; + mpi_size_t tp_size; +}; + +void mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); + +mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +void mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size); +mpi_limb_t mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize); +void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); +void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, + mpi_ptr_t tspace); + +void mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ); + + +/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/ +mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); + +/*-- mpihelp-div.c --*/ +mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); +mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize); +mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); + +/*-- mpihelp-shift.c --*/ +mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); +mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); + + +/* Define stuff for longlong.h. */ +#define W_TYPE_SIZE BITS_PER_MPI_LIMB + typedef mpi_limb_t UWtype; + typedef unsigned int UHWtype; +#if defined (__GNUC__) + typedef unsigned int UQItype __attribute__ ((mode (QI))); + typedef int SItype __attribute__ ((mode (SI))); + typedef unsigned int USItype __attribute__ ((mode (SI))); + typedef int DItype __attribute__ ((mode (DI))); + typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else + typedef unsigned char UQItype; + typedef long SItype; + typedef unsigned long USItype; +#endif + +#ifdef __GNUC__ +#include "mpi-inline.h" +#endif + +#endif /*G10_MPI_INTERNAL_H*/ diff -uNr a/smg_comms/mpi/include/mpi.h b/smg_comms/mpi/include/mpi.h --- a/smg_comms/mpi/include/mpi.h false +++ b/smg_comms/mpi/include/mpi.h d86ff3ed23ff796d0c35b550f60142dd5a7242343dcae7ca74558c30b5fec1749aaf6a0207f4bf39df464bcc60ff37a6495965d3e7dad5ad70c0aeb7a7c2a46c @@ -0,0 +1,152 @@ +/* mpi.h - Multi Precision Integers + * Modified by No Such Labs. (C) 2015. See README. + * Modified by S.MG, 2018. Added mpi_get_alloced, function for retrieving currently allocated number of limbs. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_MPI_H +#define G10_MPI_H + +#include +#include "knobs.h" +#include "types.h" +#include "memory.h" + +#ifndef EXTERN_UNLESS_MAIN_MODULE +#define EXTERN_UNLESS_MAIN_MODULE +#endif + +#define DBG_MPI mpi_debug_mode +EXTERN_UNLESS_MAIN_MODULE int mpi_debug_mode; + + +struct gcry_mpi; +typedef struct gcry_mpi *MPI; + + +/*-- mpiutil.c --*/ + +#ifdef M_DEBUG +#define mpi_alloc(n) mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +#define mpi_alloc_secure(n) mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) +#define mpi_alloc_like(n) mpi_debug_alloc_like((n), M_DBGINFO( __LINE__ ) ) +#define mpi_free(a) mpi_debug_free((a), M_DBGINFO(__LINE__) ) +#define mpi_resize(a,b) mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) +#define mpi_copy(a) mpi_debug_copy((a), M_DBGINFO(__LINE__) ) +MPI mpi_debug_alloc( unsigned nlimbs, const char *info ); +MPI mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); +MPI mpi_debug_alloc_like( MPI a, const char *info ); +void mpi_debug_free( MPI a, const char *info ); +void mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ); +MPI mpi_debug_copy( MPI a, const char *info ); +#else +MPI mpi_alloc( unsigned nlimbs ); +MPI mpi_alloc_secure( unsigned nlimbs ); +MPI mpi_alloc_like( MPI a ); +void mpi_free( MPI a ); +void mpi_resize( MPI a, unsigned nlimbs ); +MPI mpi_copy( MPI a ); +#endif +#define mpi_is_opaque(a) ((a) && (mpi_get_flags (a)&4)) +MPI mpi_set_opaque( MPI a, void *p, unsigned int len ); +void *mpi_get_opaque( MPI a, unsigned int *len ); +#define mpi_is_secure(a) ((a) && (mpi_get_flags (a)&1)) +void mpi_set_secure( MPI a ); +void mpi_clear( MPI a ); +void mpi_set( MPI w, MPI u); +void mpi_set_ui( MPI w, ulong u); +MPI mpi_alloc_set_ui( unsigned long u); +void mpi_m_check( MPI a ); +void mpi_swap( MPI a, MPI b); +int mpi_get_nlimbs (MPI a); +int mpi_get_alloced (MPI a); /* returns the allocated memory space for this MPI, in number of limbs */ +int mpi_is_neg (MPI a); +unsigned int mpi_nlimb_hint_from_nbytes (unsigned int nbytes); +unsigned int mpi_nlimb_hint_from_nbits (unsigned int nbits); +unsigned int mpi_get_flags (MPI a); + +/*-- mpicoder.c --*/ +MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure); +int mpi_fromstr(MPI val, const char *str); +int mpi_print( FILE *fp, MPI a, int mode ); +//void g10_log_mpidump( const char *text, MPI a ); +byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ); +byte *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ); +void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ); + +#define log_mpidump g10_log_mpidump + +/*-- mpi-add.c --*/ +void mpi_add_ui(MPI w, MPI u, ulong v ); +void mpi_add(MPI w, MPI u, MPI v); +void mpi_addm(MPI w, MPI u, MPI v, MPI m); +void mpi_sub_ui(MPI w, MPI u, ulong v ); +void mpi_sub( MPI w, MPI u, MPI v); +void mpi_subm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-mul.c --*/ +void mpi_mul_ui(MPI w, MPI u, ulong v ); +void mpi_mul_2exp( MPI w, MPI u, ulong cnt); +void mpi_mul( MPI w, MPI u, MPI v); +void mpi_mulm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-div.c --*/ +ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ); +void mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ); +void mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ); +void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ); +void mpi_tdiv_r( MPI rem, MPI num, MPI den); +void mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den); +void mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ); +int mpi_divisible_ui(MPI dividend, ulong divisor ); + +/*-- mpi-gcd.c --*/ +int mpi_gcd( MPI g, MPI a, MPI b ); + +/*-- mpi-pow.c --*/ +void mpi_pow( MPI w, MPI u, MPI v); +void mpi_powm( MPI res, MPI base, MPI exponent, MPI mod); + +/*-- mpi-mpow.c --*/ +void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); + +/*-- mpi-cmp.c --*/ +int mpi_cmp_ui( MPI u, ulong v ); +int mpi_cmp( MPI u, MPI v ); + +/*-- mpi-scan.c --*/ +int mpi_getbyte( MPI a, unsigned idx ); +void mpi_putbyte( MPI a, unsigned idx, int value ); +unsigned mpi_trailing_zeros( MPI a ); + +/*-- mpi-bit.c --*/ +void mpi_normalize( MPI a ); +unsigned mpi_get_nbits( MPI a ); +int mpi_test_bit( MPI a, unsigned n ); +void mpi_set_bit( MPI a, unsigned n ); +void mpi_set_highbit( MPI a, unsigned n ); +void mpi_clear_highbit( MPI a, unsigned n ); +void mpi_clear_bit( MPI a, unsigned n ); +void mpi_rshift( MPI x, MPI a, unsigned n ); + +/*-- mpi-inv.c --*/ +void mpi_invm( MPI x, MPI u, MPI v ); + +#endif /*G10_MPI_H*/ diff -uNr a/smg_comms/mpi/include/types.h b/smg_comms/mpi/include/types.h --- a/smg_comms/mpi/include/types.h false +++ b/smg_comms/mpi/include/types.h fab4d9725d153347b3e67dcbc53ed25f5f8cd8149d35b17f11ce06cd62a825368f95b95f65f394395cebe34baa02afd4f0b331d3019ba6e8b0db73a947a7878a @@ -0,0 +1,138 @@ +/* types.h - some common typedefs + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_TYPES_H +#define G10_TYPES_H + +#ifdef HAVE_INTTYPES_H +/* For uint64_t */ +#include +#endif + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT +#undef SIZEOF_UNSIGNED_SHORT +#define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT +#undef SIZEOF_UNSIGNED_INT +#define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG +#undef SIZEOF_UNSIGNED_LONG +#define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include + + +#ifndef HAVE_BYTE_TYPEDEF +#undef byte /* maybe there is a macro with this name */ +typedef unsigned char byte; +#define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF +#undef ushort /* maybe there is a macro with this name */ +typedef unsigned short ushort; +#define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF +#undef ulong /* maybe there is a macro with this name */ +typedef unsigned long ulong; +#define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF +#undef u16 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 2 +typedef unsigned int u16; +#elif SIZEOF_UNSIGNED_SHORT == 2 +typedef unsigned short u16; +#else +#error no typedef for u16 +#endif +#define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF +#undef u32 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 4 +typedef unsigned int u32; +#elif SIZEOF_UNSIGNED_LONG == 4 +typedef unsigned long u32; +#else +#error no typedef for u32 +#endif +#define HAVE_U32_TYPEDEF +#endif + +/**************** + * Warning: Some systems segfault when this u64 typedef and + * the dummy code in cipher/md.c is not available. Examples are + * Solaris and IRIX. + */ +#ifndef HAVE_U64_TYPEDEF +#undef u64 /* maybe there is a macro with this name */ +#if SIZEOF_UINT64_T == 8 +typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_INT == 8 +typedef unsigned int u64; +#define U64_C(c) (c ## U) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG == 8 +typedef unsigned long u64; +#define U64_C(c) (c ## UL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long u64; +#define U64_C(c) (c ## ULL) +#define HAVE_U64_TYPEDEF +#endif +#endif + +typedef union { + int a; + short b; + char c[1]; + long d; +#ifdef HAVE_U64_TYPEDEF + u64 e; +#endif + float f; + double g; +} PROPERLY_ALIGNED_TYPE; + +struct string_list { + struct string_list *next; + unsigned int flags; + char d[1]; +}; +typedef struct string_list *STRLIST; +typedef struct string_list *strlist_t; + +#endif /*G10_TYPES_H*/ diff -uNr a/smg_comms/mpi/include/util.h b/smg_comms/mpi/include/util.h --- a/smg_comms/mpi/include/util.h false +++ b/smg_comms/mpi/include/util.h 9cb4e6a599501ccb7615c4da88439d29c483b03d85ba4fc5a02c2b2fbf2920aede4e99f0438d86802183b05f3a113ca597a676b18d373f2d5e39d9d6f65553b2 @@ -0,0 +1,86 @@ +/* util.h + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef G10_UTIL_H +#define G10_UTIL_H + +#if defined (_WIN32) || defined (__CYGWIN32__) +#include +#endif + +#include "types.h" +#include "types.h" +#include "mpi.h" + +#define log_hexdump printf +#define log_bug printf +#define log_bug0 printf +#define log_fatal printf +#define log_error printf +#define log_info printf +#define log_warning printf +#define log_debug printf + +#define g10_log_print_prefix printf + + +#ifndef HAVE_MEMMOVE +#define memmove(d, s, n) bcopy((s), (d), (n)) +#endif + + +/**** other missing stuff ****/ +#ifndef HAVE_ATEXIT /* For SunOS */ +#define atexit(a) (on_exit((a),0)) +#endif + +#ifndef HAVE_RAISE +#define raise(a) kill(getpid(), (a)) +#endif + +/******** some macros ************/ +#ifndef STR +#define STR(v) #v +#endif +#define STR2(v) STR(v) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + +#define wipememory2(_ptr,_set,_len) do { volatile char *_vptr=(volatile char *)(_ptr); size_t _vlen=(_len); while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + +/*-- macros to replace ctype ones and avoid locale problems --*/ +#define spacep(p) (*(p) == ' ' || *(p) == '\t') +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +/* the atoi macros assume that the buffer has only valid digits */ +#define atoi_1(p) (*(p) - '0' ) +#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) +#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2)) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + +#endif /*G10_UTIL_H*/ diff -uNr a/smg_comms/mpi/memory.c b/smg_comms/mpi/memory.c --- a/smg_comms/mpi/memory.c false +++ b/smg_comms/mpi/memory.c 739f6960d138e5ab2eb53f41872bef6de1a66ee43161b6b8a69d12849f13332e48db2392566a8736d6b2bf7272dfc01aa2bfe927d917f152be75ae821de1afd6 @@ -0,0 +1,671 @@ +/* memory.c - memory allocation + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* We use our own memory allocation functions instead of plain malloc(), + * so that we can provide some special enhancements: + * a) functions to provide memory from a secure memory. + * b) by looking at the requested allocation size we + * can reuse memory very quickly (e.g. MPI storage) + * (really needed?) + * c) memory usage reporting if compiled with M_DEBUG + * d) memory checking if compiled with M_GUARD + */ + +#include +#include +#include +#include + +#include "knobs.h" +#include "types.h" +#include "memory.h" +#include "util.h" + +#define MAGIC_NOR_BYTE 0x55 +#define MAGIC_SEC_BYTE 0xcc +#define MAGIC_END_BYTE 0xaa + +/* This is a very crude alignment check which does not work on all CPUs + * IIRC, I once introduced it for testing on an Alpha. We should better + * replace this guard stuff with one provided by a modern malloc library + */ +#if SIZEOF_UNSIGNED_LONG == 8 +#define EXTRA_ALIGN 4 +#else +#define EXTRA_ALIGN 0 +#endif + +#if defined(M_DEBUG) || defined(M_GUARD) + static void membug( const char *fmt, ... ); +#endif + +#ifdef M_DEBUG + +#ifndef M_GUARD +#define M_GUARD 1 +#endif +#undef xmalloc +#undef xtrymalloc +#undef xmalloc_clear +#undef xmalloc_secure +#undef xmalloc_secure_clear +#undef xrealloc +#undef xfree +#undef m_check +#undef xstrdup +#undef xtrystrdup +#define FNAME(a) m_debug_ ##a +#define FNAMEX(a) m_debug_ ##a +#define FNAMEXM(a) m_debug_ ##a +#define FNAMEPRT , const char *info +#define FNAMEARG , info + +#define store_len(p,n,m) do { add_entry(p,n,m, \ + info, __FUNCTION__); } while(0) +#else +#define FNAME(a) m_ ##a +#define FNAMEX(a) x ##a +#define FNAMEXM(a) xm ##a +#define FNAMEPRT +#define FNAMEARG +#define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \ + ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \ + ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \ + ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \ + : MAGIC_NOR_BYTE; \ + } while(0) +#endif + + +#ifdef M_GUARD +static long used_memory; +#endif + +#ifdef M_DEBUG /* stuff used for memory debuging */ + +struct info_entry { + struct info_entry *next; + unsigned count; /* call count */ + const char *info; /* the reference to the info string */ +}; + +struct memtbl_entry { + const void *user_p; /* for reference: the pointer given to the user */ + size_t user_n; /* length requested by the user */ + struct memtbl_entry *next; /* to build a list of unused entries */ + const struct info_entry *info; /* points into the table with */ + /* the info strings */ + unsigned inuse:1; /* this entry is in use */ + unsigned count:31; +}; + + +#define INFO_BUCKETS 53 +#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS ) +static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */ + +static struct memtbl_entry *memtbl; /* the table with the memory info */ +static unsigned memtbl_size; /* number of allocated entries */ +static unsigned memtbl_len; /* number of used entries */ +static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */ + +static void dump_table_at_exit(void); +static void dump_table(void); +static void check_allmem( const char *info ); + +/**************** + * Put the new P into the debug table and return a pointer to the table entry. + * mode is true for security. BY is the name of the function which called us. + */ +static void +add_entry( byte *p, unsigned n, int mode, const char *info, const char *by ) +{ + unsigned index; + struct memtbl_entry *e; + struct info_entry *ie; + + if( memtbl_len < memtbl_size ) + index = memtbl_len++; + else { + struct memtbl_entry *e; + /* look for a used entry in the table. We take the first one, + * so that freed entries remain as long as possible in the table + * (free appends a new one) + */ + if( (e = memtbl_unused) ) { + index = e - memtbl; + memtbl_unused = e->next; + e->next = NULL; + } + else { /* no free entries in the table: extend the table */ + if( !memtbl_size ) { /* first time */ + memtbl_size = 100; + if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) ) + membug("memory debug table malloc failed\n"); + index = 0; + memtbl_len = 1; + atexit( dump_table_at_exit ); + } + else { /* realloc */ + unsigned n = memtbl_size / 4; /* enlarge by 25% */ + if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl))) + membug("memory debug table realloc failed\n"); + memset(memtbl+memtbl_size, 0, n*sizeof *memtbl ); + memtbl_size += n; + index = memtbl_len++; + } + } + } + e = memtbl+index; + if( e->inuse ) + membug("Ooops: entry %u is flagged as in use\n", index); + e->user_p = p + EXTRA_ALIGN + 4; + e->user_n = n; + e->count++; + if( e->next ) + membug("Ooops: entry is in free entry list\n"); + /* do we already have this info string */ + for( ie = info_strings[info_hash(info)]; ie; ie = ie->next ) + if( ie->info == info ) + break; + if( !ie ) { /* no: make a new entry */ + if( !(ie = malloc( sizeof *ie )) ) + membug("can't allocate info entry\n"); + ie->next = info_strings[info_hash(info)]; + info_strings[info_hash(info)] = ie; + ie->info = info; + ie->count = 0; + } + ie->count++; + e->info = ie; + e->inuse = 1; + + /* put the index at the start of the memory */ + p[EXTRA_ALIGN+0] = index; + p[EXTRA_ALIGN+1] = index >> 8 ; + p[EXTRA_ALIGN+2] = index >> 16 ; + p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ; + if( DBG_MEMORY ) + log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by ); +} + + + +/**************** + * Check that the memory block is correct. The magic byte has already been + * checked. Checks which are done here: + * - see whether the index points into our memory table + * - see whether P is the same as the one stored in the table + * - see whether we have already freed this block. + */ +struct memtbl_entry * +check_mem( const byte *p, const char *info ) +{ + unsigned n; + struct memtbl_entry *e; + + n = p[EXTRA_ALIGN+0]; + n |= p[EXTRA_ALIGN+1] << 8; + n |= p[EXTRA_ALIGN+2] << 16; + + if( n >= memtbl_len ) + membug("memory at %p corrupted: index=%u table_len=%u (%s)\n", + p+EXTRA_ALIGN+4, n, memtbl_len, info ); + e = memtbl+n; + + if( e->user_p != p+EXTRA_ALIGN+4 ) + membug("memory at %p corrupted: reference mismatch (%s)\n", + p+EXTRA_ALIGN+4, info ); + if( !e->inuse ) + membug("memory at %p corrupted: marked as free (%s)\n", + p+EXTRA_ALIGN+4, info ); + + if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE + || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) ) + membug("memory at %p corrupted: underflow=%02x (%s)\n", + p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info ); + if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE ) + membug("memory at %p corrupted: overflow=%02x (%s)\n", + p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info ); + return e; +} + + +/**************** + * free the entry and the memory (replaces free) + */ +static void +free_entry( byte *p, const char *info ) +{ + struct memtbl_entry *e, *e2; + + check_allmem("add_entry"); + + e = check_mem(p, info); + if( DBG_MEMORY ) + log_debug( "%s frees %u bytes alloced by %s\n", + info, e->user_n, e->info->info ); + if( !e->inuse ) { + if( e->user_p == p + EXTRA_ALIGN+ 4 ) + membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 ); + else + membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 ); + } + + e->inuse = 0; + e->next = NULL; + if( !memtbl_unused ) + memtbl_unused = e; + else { + for(e2=memtbl_unused; e2->next; e2 = e2->next ) + ; + e2->next = e; + } + if( m_is_secure(p+EXTRA_ALIGN+4) ) + secmem_free(p); + else { + memset(p,'f', e->user_n+5); + free(p); + } +} + +static void +dump_entry(struct memtbl_entry *e ) +{ + unsigned n = e - memtbl; + + fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n", + n, e->inuse?'a':'u', e->count, e->user_p, e->user_n, + e->info->info, e->info->count ); + + +} + + +static void +dump_table_at_exit( void) +{ + if( DBG_MEMSTAT ) + dump_table(); +} + +static void +dump_table( void) +{ + unsigned n; + struct memtbl_entry *e; + ulong sum = 0, chunks =0; + + for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { + if(e->inuse) { + dump_entry(e); + sum += e->user_n; + chunks++; + } + } + fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n", + sum, chunks ); +} + + +static void +check_allmem( const char *info ) +{ + unsigned n; + struct memtbl_entry *e; + + for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { + if( e->inuse ) { + check_mem(e->user_p-4-EXTRA_ALIGN, info); + } + } +} + +#endif /* M_DEBUG */ + +#if defined(M_DEBUG) || defined(M_GUARD) +static void +membug( const char *fmt, ... ) +{ + va_list arg_ptr ; + + fprintf(stderr, "\nMemory Error: " ) ; + va_start( arg_ptr, fmt ) ; + vfprintf(stderr,fmt,arg_ptr) ; + va_end(arg_ptr); + fflush(stderr); +#ifdef M_DEBUG + if( DBG_MEMSTAT ) + dump_table(); +#endif + abort(); +} +#endif + +void +m_print_stats( const char *prefix ) +{ +#ifdef M_DEBUG + unsigned n; + struct memtbl_entry *e; + ulong sum = 0, chunks =0; + + for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { + if(e->inuse) { + sum += e->user_n; + chunks++; + } + } + + log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n", + prefix? prefix:"", prefix? ": ":"", sum, chunks ); +#elif defined(M_GUARD) + log_debug( "%s%smemstat: %8ld bytes\n", + prefix? prefix:"", prefix? ": ":"", used_memory ); +#endif +} + +void +m_dump_table( const char *prefix ) +{ +#ifdef M_DEBUG + fprintf(stderr,"Memory-Table-Dump: %s\n", prefix); + dump_table(); +#endif + m_print_stats( prefix ); +} + + +static void +out_of_core(size_t n, int secure) +{ + log_error ("out of %s memory while allocating %u bytes\n", + secure? "secure":"" ,(unsigned)n ); + if (secure) { + /*secmem_dump_stats ();*/ + log_info ("(this may be caused by too many secret keys used " + "simultaneously or due to excessive large key sizes)\n"); + } + exit(2); +} + +/**************** + * Allocate memory of size n. + * This function gives up if we do not have enough memory + */ +void * +FNAMEXM(alloc)( size_t n FNAMEPRT ) +{ + char *p; + +#ifdef M_GUARD + if(!n) + out_of_core(n,0); /* should never happen */ + if( !(p = malloc( n + EXTRA_ALIGN+5 )) ) + out_of_core(n,0); + store_len(p,n,0); + used_memory += n; + p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; + return p+EXTRA_ALIGN+4; +#else + /* mallocing zero bytes is undefined by ISO-C, so we better make + sure that it won't happen */ + if (!n) + n = 1; + if( !(p = malloc( n )) ) + out_of_core(n,0); + return p; +#endif +} + +/* Allocate memory of size n. This function returns NULL if we do not + have enough memory. */ +void * +FNAMEX(trymalloc)(size_t n FNAMEPRT) +{ +#ifdef M_GUARD + char *p; + + if (!n) + n = 1; + p = malloc (n + EXTRA_ALIGN+5); + if (!p) + return NULL; + store_len(p,n,0); + used_memory += n; + p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; + return p+EXTRA_ALIGN+4; +#else + /* Mallocing zero bytes is undefined by ISO-C, so we better make + sure that it won't happen. */ + return malloc (n? n: 1); +#endif +} + +/**************** + * Allocate memory of size n from the secure memory pool. + * This function gives up if we do not have enough memory + */ +void * +FNAMEXM(alloc_secure)( size_t n FNAMEPRT ) +{ + char *p; + +#ifdef M_GUARD + if(!n) + out_of_core(n,1); /* should never happen */ + if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) ) + out_of_core(n,1); + store_len(p,n,1); + p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; + return p+EXTRA_ALIGN+4; +#else + /* mallocing zero bytes is undefined by ISO-C, so we better make + sure that it won't happen */ + if (!n) + n = 1; + if( !(p = secmem_malloc( n )) ) + out_of_core(n,1); + return p; +#endif +} + +void * +FNAMEXM(alloc_clear)( size_t n FNAMEPRT ) +{ + void *p; + p = FNAMEXM(alloc)( n FNAMEARG ); + memset(p, 0, n ); + return p; +} + +void * +FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT) +{ + void *p; + p = FNAMEXM(alloc_secure)( n FNAMEARG ); + memset(p, 0, n ); + return p; +} + + +/**************** + * realloc and clear the old space + */ +void * +FNAMEX(realloc)( void *a, size_t n FNAMEPRT ) +{ + void *b; + +#ifdef M_GUARD + if( a ) { +#error "--enable-m-guard does not currently work" + unsigned char *p = a; + size_t len = m_size(a); + + if( len >= n ) /* we don't shrink for now */ + return a; + if( p[-1] == MAGIC_SEC_BYTE ) + b = FNAME(alloc_secure_clear)(n FNAMEARG); + else + b = FNAME(alloc_clear)(n FNAMEARG); + FNAME(check)(NULL FNAMEARG); + memcpy(b, a, len ); + FNAME(free)(p FNAMEARG); + } + else + b = FNAME(alloc)(n FNAMEARG); +#else + if( m_is_secure(a) ) { + if( !(b = secmexrealloc( a, n )) ) + out_of_core(n,1); + } + else { + if( !(b = realloc( a, n )) ) + out_of_core(n,0); + } +#endif + + return b; +} + + + +/**************** + * Free a pointer + */ +void +FNAMEX(free)( void *a FNAMEPRT ) +{ + byte *p = a; + + if( !p ) + return; +#ifdef M_DEBUG + free_entry(p-EXTRA_ALIGN-4, info); +#elif defined M_GUARD + m_check(p); + if( m_is_secure(a) ) + secmem_free(p-EXTRA_ALIGN-4); + else { + used_memory -= m_size(a); + free(p-EXTRA_ALIGN-4); + } +#else + if( m_is_secure(a) ) + secmem_free(p); + else + free(p); +#endif +} + + +void +FNAME(check)( const void *a FNAMEPRT ) +{ +#ifdef M_GUARD + const byte *p = a; + +#ifdef M_DEBUG + if( p ) + check_mem(p-EXTRA_ALIGN-4, info); + else + check_allmem(info); +#else + if( !p ) + return; + if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) ) + membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] ); + else if( p[m_size(p)] != MAGIC_END_BYTE ) + membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] ); +#endif +#endif +} + + +size_t +m_size( const void *a ) +{ +#ifndef M_GUARD + log_debug("dummy m_size called\n"); + return 0; +#else + const byte *p = a; + size_t n; + +#ifdef M_DEBUG + n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n; +#else + n = ((byte*)p)[-4]; + n |= ((byte*)p)[-3] << 8; + n |= ((byte*)p)[-2] << 16; +#endif + return n; +#endif +} + + +char * +FNAMEX(strdup)( const char *a FNAMEPRT ) +{ + size_t n = strlen(a); + char *p = FNAMEXM(alloc)(n+1 FNAMEARG); + strcpy(p, a); + return p; +} + +char * +FNAMEX(trystrdup)(const char *a FNAMEPRT) +{ + size_t n = strlen (a); + char *p = FNAMEX(trymalloc)(n+1 FNAMEARG); + if (p) + strcpy (p, a); + return p; +} + + +/* Wrapper around xmalloc_clear to take the usual 2 arguments of a + calloc style function. */ +void * +xcalloc (size_t n, size_t m) +{ + size_t nbytes; + + nbytes = n * m; + if (m && nbytes / m != n) + out_of_core (nbytes, 0); + return xmalloc_clear (nbytes); +} + +/* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments + of a calloc style function. */ +void * +xcalloc_secure (size_t n, size_t m) +{ + size_t nbytes; + + nbytes = n * m; + if (m && nbytes / m != n) + out_of_core (nbytes, 1); + return xmalloc_secure_clear (nbytes); +} diff -uNr a/smg_comms/mpi/mpi-add.c b/smg_comms/mpi/mpi-add.c --- a/smg_comms/mpi/mpi-add.c false +++ b/smg_comms/mpi/mpi-add.c 1d6a019fd026bf2712be8e24eb9bac995524336df8ea4bf08878bda3f95a943139e68381347974feea6ddaf3748ecd837fd698875324cb16c2af13af1e54baa0 @@ -0,0 +1,240 @@ +/* mpi-add.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + + +/**************** + * Add the unsigned integer V to the mpi-integer U and store the + * result in W. U and V may be the same. + */ +void +mpi_add_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + } + else if( !usign ) { /* mpi is not negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + wsign = 1; + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +mpi_add(MPI w, MPI u, MPI v) +{ + mpi_ptr_t wp, up, vp; + mpi_size_t usize, vsize, wsize; + int usign, vsign, wsign; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + vsize = u->nlimbs; + vsign = u->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = v->d; + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + vsize = v->nlimbs; + vsign = v->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + } + wp = w->d; + wsign = 0; + + if( !vsize ) { /* simple */ + MPN_COPY(wp, up, usize ); + wsize = usize; + wsign = usign; + } + else if( usign != vsign ) { /* different sign */ + /* This test is right since USIZE >= VSIZE */ + if( usize != vsize ) { + mpihelp_sub(wp, up, usize, vp, vsize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + wsign = usign; + } + else if( mpihelp_cmp(up, vp, usize) < 0 ) { + mpihelp_sub_n(wp, vp, up, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( !usign ) + wsign = 1; + } + else { + mpihelp_sub_n(wp, up, vp, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( usign ) + wsign = 1; + } + } + else { /* U and V have same sign. Add them. */ + mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize); + wp[usize] = cy; + wsize = usize + cy; + if( usign ) + wsign = 1; + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +/**************** + * Subtract the unsigned integer V from the mpi-integer U and store the + * result in W. + */ +void +mpi_sub_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + wsign = 1; + } + else if( usign ) { /* mpi and v are negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + wsign = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + +void +mpi_sub(MPI w, MPI u, MPI v) +{ + if( w == v ) { + MPI vv = mpi_copy(v); + vv->sign = !vv->sign; + mpi_add( w, u, vv ); + mpi_free(vv); + } + else { + /* fixme: this is not thread-save (we temp. modify v) */ + v->sign = !v->sign; + mpi_add( w, u, v ); + v->sign = !v->sign; + } +} + + +void +mpi_addm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_add(w, u, v); + mpi_fdiv_r( w, w, m ); +} + +void +mpi_subm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_sub(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff -uNr a/smg_comms/mpi/mpi-bit.c b/smg_comms/mpi/mpi-bit.c --- a/smg_comms/mpi/mpi-bit.c false +++ b/smg_comms/mpi/mpi-bit.c 36aa7bc45976c3792b00414443b35c0de1c172b5d2ddf26ff62736cf8642f3d2260fd45216f075da1024a27ced6e03004a41cc3a7508877462a7a06c11ea4339 @@ -0,0 +1,262 @@ +/* mpi-bit.c - MPI bit level fucntions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +__clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + +#define A_LIMB_1 ((mpi_limb_t)1) + + +/**************** + * Sometimes we have MSL (most significant limbs) which are 0; + * this is for some reasons not good, so this function removes them. + */ +void +mpi_normalize( MPI a ) +{ + if( mpi_is_opaque (a) ) + return; + + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) + ; +} + + + +/**************** + * Return the number of bits in A. + */ +unsigned +mpi_get_nbits( MPI a ) +{ + unsigned n; + + mpi_normalize( a ); + if( a->nlimbs ) { + mpi_limb_t alimb = a->d[a->nlimbs-1]; + if( alimb ) + count_leading_zeros( n, alimb ); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; + } + else + n = 0; + return n; +} + + +/**************** + * Test whether bit N is set. + */ +int +mpi_test_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + mpi_limb_t limb; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return 0; /* too far left: this is a 0 */ + limb = a->d[limbno]; + return (limb & (A_LIMB_1 << bitno))? 1: 0; +} + + +/**************** + * Set bit N of A. + */ +void +mpi_set_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * clear bit N of A and all bits above + */ +void +mpi_clear_highbit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* not allocated, so no effect */ + + for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + + /* adjust nlimbs to clear any leading zero-value limbs (normalize) */ + a->nlimbs = limbno+1; + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ); + +} + +/**************** + * Clear bit N of A. + */ +void +mpi_clear_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* don't need to clear this bit, it's to far to left */ + a->d[limbno] &= ~(A_LIMB_1 << bitno); +} + + +/**************** + * Shift A by N bits to the right + * FIXME: should use alloc_limb if X and A are same. + */ +void +mpi_rshift( MPI x, MPI a, unsigned n ) +{ + mpi_ptr_t xp; + mpi_size_t xsize; + + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED(x, xsize); + xp = x->d; + + if( xsize ) { + mpihelp_rshift( xp, a->d, xsize, n); + MPN_NORMALIZE( xp, xsize); + } + x->nlimbs = xsize; +} + + +/**************** + * Shift A by COUNT limbs to the left + * This is used only within the MPI library + */ +void +mpi_lshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + int n = a->nlimbs; + int i; + + if( !count || !n ) + return; + + RESIZE_IF_NEEDED( a, n+count ); + + for( i = n-1; i >= 0; i-- ) + ap[i+count] = ap[i]; + for(i=0; i < count; i++ ) + ap[i] = 0; + a->nlimbs += count; +} + + +/**************** + * Shift A by COUNT limbs to the right + * This is used only within the MPI library + */ +void +mpi_rshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + mpi_size_t n = a->nlimbs; + unsigned int i; + + if( count >= n ) { + a->nlimbs = 0; + return; + } + + for( i = 0; i < n - count; i++ ) + ap[i] = ap[i+count]; + ap[i] = 0; + a->nlimbs -= count; +} + + diff -uNr a/smg_comms/mpi/mpi-cmp.c b/smg_comms/mpi/mpi-cmp.c --- a/smg_comms/mpi/mpi-cmp.c false +++ b/smg_comms/mpi/mpi-cmp.c 9225d6faa31311ea2857e6c9a8ad497846f41eca0bf07b0ebc7601b05251af751e68226ce7bb6b9f261fb182a5be9bb1a05aee4f222764d2f9ca28bfc59cfa99 @@ -0,0 +1,77 @@ +/* mpi-cmp.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + +int +mpi_cmp_ui( MPI u, unsigned long v ) +{ + mpi_limb_t limb = v; + + mpi_normalize( u ); + if( !u->nlimbs && !limb ) + return 0; + if( u->sign ) + return -1; + if( u->nlimbs > 1 ) + return 1; + + if( u->d[0] == limb ) + return 0; + else if( u->d[0] > limb ) + return 1; + else + return -1; +} + +int +mpi_cmp( MPI u, MPI v ) +{ + mpi_size_t usize, vsize; + int cmp; + + mpi_normalize( u ); + mpi_normalize( v ); + usize = u->nlimbs; + vsize = v->nlimbs; + if( !u->sign && v->sign ) + return 1; + if( u->sign && !v->sign ) + return -1; + if( usize != vsize && !u->sign && !v->sign ) + return usize - vsize; + if( usize != vsize && u->sign && v->sign ) + return vsize + usize; + if( !usize ) + return 0; + if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) ) + return 0; + if( (cmp < 0?1:0) == (u->sign?1:0)) + return 1; + return -1; +} + + diff -uNr a/smg_comms/mpi/mpi-div.c b/smg_comms/mpi/mpi-div.c --- a/smg_comms/mpi/mpi-div.c false +++ b/smg_comms/mpi/mpi-div.c 4c816e02a36adbcae224e0f6ecbef7d46811a2add9d33b677165936bee0d5e8b4900490904c25e0eae3e8616cc3bd7f7df13269ea4adde641814be563f820667 @@ -0,0 +1,316 @@ +/* mpi-div.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + + +void +mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + /* We need the original value of the divisor after the remainder has been + * preliminary calculated. We have to copy it to temporary space if it's + * the same variable as REM. */ + if( rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_r( rem, dividend, divisor ); + + if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) + mpi_add( rem, rem, divisor); + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + + +/**************** + * Division rounding the quotient towards -infinity. + * The remainder gets the same sign as the denominator. + * rem is optional + */ + +ulong +mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ) +{ + mpi_limb_t rlimb; + + rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); + if( rlimb && dividend->sign ) + rlimb = divisor - rlimb; + + if( rem ) { + rem->d[0] = rlimb; + rem->nlimbs = rlimb? 1:0; + } + return rlimb; +} + + +void +mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ) +{ + MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) ); + mpi_fdiv_qr( quot, tmp, dividend, divisor); + mpi_free(tmp); +} + +void +mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + if( quot == divisor || rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_qr( quot, rem, dividend, divisor ); + + if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { + mpi_sub_ui( quot, quot, 1 ); + mpi_add( rem, rem, divisor); + } + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + +/* If den == quot, den needs temporary storage. + * If den == rem, den needs temporary storage. + * If num == quot, num needs temporary storage. + * If den has temporary storage, it can be normalized while being copied, + * i.e no extra storage should be allocated. + */ + +void +mpi_tdiv_r( MPI rem, MPI num, MPI den) +{ + mpi_tdiv_qr(NULL, rem, num, den ); +} + +void +mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den) +{ + mpi_ptr_t np, dp; + mpi_ptr_t qp, rp; + mpi_size_t nsize = num->nlimbs; + mpi_size_t dsize = den->nlimbs; + mpi_size_t qsize, rsize; + mpi_size_t sign_remainder = num->sign; + mpi_size_t sign_quotient = num->sign ^ den->sign; + unsigned normalization_steps; + mpi_limb_t q_limb; + mpi_ptr_t marker[5]; + int markidx=0; + + /* Ensure space is enough for quotient and remainder. + * We need space for an extra limb in the remainder, because it's + * up-shifted (normalized) below. */ + rsize = nsize + 1; + mpi_resize( rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if( qsize <= 0 ) { + if( num != rem ) { + rem->nlimbs = num->nlimbs; + rem->sign = num->sign; + MPN_COPY(rem->d, num->d, nsize); + } + if( quot ) { + /* This needs to follow the assignment to rem, in case the + * numerator and quotient are the same. */ + quot->nlimbs = 0; + quot->sign = 0; + } + return; + } + + if( quot ) + mpi_resize( quot, qsize); + + /* Read pointers here, when reallocation is finished. */ + np = num->d; + dp = den->d; + rp = rem->d; + + /* Optimize division by a single-limb divisor. */ + if( dsize == 1 ) { + mpi_limb_t rlimb; + if( quot ) { + qp = quot->d; + rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] ); + qsize -= qp[qsize - 1] == 0; + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + else + rlimb = mpihelp_mod_1( np, nsize, dp[0] ); + rp[0] = rlimb; + rsize = rlimb != 0?1:0; + rem->nlimbs = rsize; + rem->sign = sign_remainder; + return; + } + + + if( quot ) { + qp = quot->d; + /* Make sure QP and NP point to different objects. Otherwise the + * numerator would be gradually overwritten by the quotient limbs. */ + if(qp == np) { /* Copy NP object to temporary space. */ + np = marker[markidx++] = mpi_alloc_limb_space(nsize, + mpi_is_secure(quot)); + MPN_COPY(np, qp, nsize); + } + } + else /* Put quotient at top of remainder. */ + qp = rp + dsize; + + count_leading_zeros( normalization_steps, dp[dsize - 1] ); + + /* Normalize the denominator, i.e. make its most significant bit set by + * shifting it NORMALIZATION_STEPS bits to the left. Also shift the + * numerator the same number of steps (to keep the quotient the same!). + */ + if( normalization_steps ) { + mpi_ptr_t tp; + mpi_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + * the most significant word. Use temporary storage not to clobber + * the original contents of the denominator. */ + tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); + mpihelp_lshift( tp, dp, dsize, normalization_steps ); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + * significant word. Move the shifted numerator in the remainder + * meanwhile. */ + nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps); + if( nlimb ) { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else { + /* The denominator is already normalized, as required. Copy it to + * temporary space if it overlaps with the quotient or remainder. */ + if( dp == rp || (quot && (dp == qp))) { + mpi_ptr_t tp; + + tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den)); + MPN_COPY( tp, dp, dsize ); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if( rp != np ) + MPN_COPY(rp, np, nsize); + + rsize = nsize; + } + + q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize ); + + if( quot ) { + qsize = rsize - dsize; + if(q_limb) { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if( normalization_steps && rsize ) { + mpihelp_rshift(rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0?1:0; + } + + rem->nlimbs = rsize; + rem->sign = sign_remainder; + while( markidx ) + mpi_free_limb_space(marker[--markidx]); +} + +void +mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ) +{ + mpi_size_t usize, wsize; + mpi_size_t limb_cnt; + + usize = u->nlimbs; + limb_cnt = count / BITS_PER_MPI_LIMB; + wsize = usize - limb_cnt; + if( limb_cnt >= usize ) + w->nlimbs = 0; + else { + mpi_ptr_t wp; + mpi_ptr_t up; + + RESIZE_IF_NEEDED( w, wsize ); + wp = w->d; + up = u->d; + + count %= BITS_PER_MPI_LIMB; + if( count ) { + mpihelp_rshift( wp, up + limb_cnt, wsize, count ); + wsize -= !wp[wsize - 1]; + } + else { + MPN_COPY_INCR( wp, up + limb_cnt, wsize); + } + + w->nlimbs = wsize; + } +} + +/**************** + * Check whether dividend is divisible by divisor + * (note: divisor must fit into a limb) + */ +int +mpi_divisible_ui(MPI dividend, ulong divisor ) +{ + return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); +} + diff -uNr a/smg_comms/mpi/mpi-gcd.c b/smg_comms/mpi/mpi-gcd.c --- a/smg_comms/mpi/mpi-gcd.c false +++ b/smg_comms/mpi/mpi-gcd.c 0ad3099f1db858eb1d25e7bccc7461f981adab9f7853346ef97a161639d3bcc31f22539abb342c96eb087f0fce3c91bb26a7e9c78c92dc33ca1fca5efcf534fe @@ -0,0 +1,57 @@ +/* mpi-gcd.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + +/**************** + * Find the greatest common divisor G of A and B. + * Return: true if this 1, false in all other cases + */ +int +mpi_gcd( MPI g, MPI xa, MPI xb ) +{ + MPI a, b; + + a = mpi_copy(xa); + b = mpi_copy(xb); + + /* TAOCP Vol II, 4.5.2, Algorithm A */ + a->sign = 0; + b->sign = 0; + while( mpi_cmp_ui( b, 0 ) ) { + mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ + mpi_set(a,b); + mpi_set(b,g); + } + mpi_set(g, a); + + mpi_free(a); + mpi_free(b); + return !mpi_cmp_ui( g, 1); +} + + + diff -uNr a/smg_comms/mpi/mpi-inline.c b/smg_comms/mpi/mpi-inline.c --- a/smg_comms/mpi/mpi-inline.c false +++ b/smg_comms/mpi/mpi-inline.c f9c2a485a76a2a0c12704d4683a4dc6a891b82217eb70b6fee22d4cde87fe7453c99463136a677c4520f9ace2b110ebd856214afdec5104eb2cb0774573f09ca @@ -0,0 +1,39 @@ +/* mpi-inline.c + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" + +/* put the inline functions as real functions into the lib */ +#define G10_MPI_INLINE_DECL + +#include "mpi-internal.h" + +/* always include the header becuase it is only + * included by mpi-internal if __GCC__ is defined but we + * need it here in all cases and the above definition of + * of the macro allows us to do so + */ +#include "mpi-inline.h" + diff -uNr a/smg_comms/mpi/mpi-inv.c b/smg_comms/mpi/mpi-inv.c --- a/smg_comms/mpi/mpi-inv.c false +++ b/smg_comms/mpi/mpi-inv.c bd7b8bd954f2ddd627a55179b48c589dee37155ba3a2984c0e7ad6cc32c1c4a53dd0e9be5bd9a1ec1b6ee9c04e98dd40adfb2fec78bd2f24ff4e6ec6f723cb55 @@ -0,0 +1,270 @@ +/* mpi-inv.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + + +/**************** + * Calculate the multiplicative inverse X of A mod N + * That is: Find the solution x for + * 1 = (a*x) mod n + */ +void +mpi_invm( MPI x, MPI a, MPI n ) +{ +#if 0 + MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; + MPI ta, tb, tc; + + u = mpi_copy(a); + v = mpi_copy(n); + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_alloc_set_ui(0); + v2 = mpi_alloc_set_ui(1); + v3 = mpi_copy(v); + q = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + while( mpi_cmp_ui( v3, 0 ) ) { + mpi_fdiv_q( q, u3, v3 ); + mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); + mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); + mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); + mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); + } + /* log_debug("result:\n"); + log_mpidump("q =", q ); + log_mpidump("u1=", u1); + log_mpidump("u2=", u2); + log_mpidump("u3=", u3); + log_mpidump("v1=", v1); + log_mpidump("v2=", v2); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(q); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + mpi_free(u); + mpi_free(v); +#elif 0 + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 */ + + /* FIXME: we can simplify this in most cases (see Knuth) */ + MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; + unsigned k; + int sign; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + + + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); /* !-- used as const 1 */ + v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); +#else + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 + * with further enhancement */ + MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); + + mpi_free(u); + mpi_free(v); +#endif +} diff -uNr a/smg_comms/mpi/mpi-mpow.c b/smg_comms/mpi/mpi-mpow.c --- a/smg_comms/mpi/mpi-mpow.c false +++ b/smg_comms/mpi/mpi-mpow.c 221190b0f2bade0e8f32e7abb9a0cda81a2b15a0abe6ab54596b4823c41149ebb93338fa4ce7c6c4809618a53a173003f7febd510f188509e0d7fdd466596130 @@ -0,0 +1,103 @@ +/* mpi-mpow.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int idx = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + idx <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + idx |= 1; + } + return idx; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + + for(k=0; basearray[k]; k++ ) + ; + assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + assert(i==k); + assert(t); + assert( k < 10 ); + + G = xmalloc_clear( (1<= 0 && idx < (1<. + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + + +void +mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult ) +{ + mpi_size_t size, prod_size; + mpi_ptr_t prod_ptr; + mpi_limb_t cy; + int sign; + + size = mult->nlimbs; + sign = mult->sign; + + if( !size || !small_mult ) { + prod->nlimbs = 0; + prod->sign = 0; + return; + } + + prod_size = size + 1; + if( prod->alloced < prod_size ) + mpi_resize( prod, prod_size ); + prod_ptr = prod->d; + + cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); + if( cy ) + prod_ptr[size++] = cy; + prod->nlimbs = size; + prod->sign = sign; +} + + +void +mpi_mul_2exp( MPI w, MPI u, unsigned long cnt) +{ + mpi_size_t usize, wsize, limb_cnt; + mpi_ptr_t wp; + mpi_limb_t wlimb; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + + if( !usize ) { + w->nlimbs = 0; + w->sign = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MPI_LIMB; + wsize = usize + limb_cnt + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize ); + wp = w->d; + wsize = usize + limb_cnt; + wsign = usign; + + cnt %= BITS_PER_MPI_LIMB; + if( cnt ) { + wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt ); + if( wlimb ) { + wp[wsize] = wlimb; + wsize++; + } + } + else { + MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + * mpn_lshift, not to lose for U == W. */ + MPN_ZERO( wp, limb_cnt ); + + w->nlimbs = wsize; + w->sign = wsign; +} + + + +void +mpi_mul( MPI w, MPI u, MPI v) +{ + mpi_size_t usize, vsize, wsize; + mpi_ptr_t up, vp, wp; + mpi_limb_t cy; + int usign, vsign, usecure, vsecure, sign_product; + int assign_wp=0; + mpi_ptr_t tmp_limb=NULL; + + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + usecure = mpi_is_secure(v); + up = v->d; + vsize = u->nlimbs; + vsign = u->sign; + vsecure = mpi_is_secure(u); + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + usecure = mpi_is_secure(u); + up = u->d; + vsize = v->nlimbs; + vsign = v->sign; + vsecure = mpi_is_secure(v); + vp = v->d; + } + sign_product = usign ^ vsign; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { + /* w is not allocated in secure space but u or v is. To make sure + * that no temporray results are stored in w, we temporary use + * a newly allocated limb space for w */ + wp = mpi_alloc_limb_space( wsize, 1 ); + assign_wp = 2; /* mark it as 2 so that we can later copy it back to + * mormal memory */ + } + else if( w->alloced < wsize ) { + if( wp == up || wp == vp ) { + wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); + assign_wp = 1; + } + else { + mpi_resize(w, wsize ); + wp = w->d; + } + } + else { /* Make U and V not overlap with W. */ + if( wp == up ) { + /* W and U are identical. Allocate temporary space for U. */ + up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); + /* Is V identical too? Keep it identical with U. */ + if( wp == vp ) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY( up, wp, usize ); + } + else if( wp == vp ) { + /* W and V are identical. Allocate temporary space for V. */ + vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); + /* Copy to the temporary space. */ + MPN_COPY( vp, wp, vsize ); + } + } + + if( !vsize ) + wsize = 0; + else { + cy = mpihelp_mul( wp, up, usize, vp, vsize ); + wsize -= cy? 0:1; + } + + if( assign_wp ) { + if (assign_wp == 2) { + /* copy the temp wp from secure memory back to normal memory */ + mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); + MPN_COPY (tmp_wp, wp, wsize); + mpi_free_limb_space (wp); + wp = tmp_wp; + } + mpi_assign_limb_space( w, wp, wsize ); + } + w->nlimbs = wsize; + w->sign = sign_product; + if( tmp_limb ) + mpi_free_limb_space( tmp_limb ); +} + + +void +mpi_mulm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_mul(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff -uNr a/smg_comms/mpi/mpi-pow.c b/smg_comms/mpi/mpi-pow.c --- a/smg_comms/mpi/mpi-pow.c false +++ b/smg_comms/mpi/mpi-pow.c bbb0c95d94298e81a2357fda16069a02ab02dc1b36a48e6585200df41e235c56ea25317c5a851aa7e9f5c5c5fbea684d039377205030715c3fd8e06f31d3ba6d @@ -0,0 +1,291 @@ +/* mpi-pow.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + + +/**************** + * RES = BASE ^ EXP mod MOD + */ +void +mpi_powm( MPI res, MPI base, MPI exponent, MPI mod) +{ + mpi_ptr_t rp, ep, mp, bp; + mpi_size_t esize, msize, bsize, rsize; + int esign, msign, bsign, rsign; + int esec, msec, bsec, rsec; + mpi_size_t size; + int mod_shift_cnt; + int negative_result; + mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL; + mpi_ptr_t xp_marker=NULL; + int assign_rp=0; + mpi_ptr_t tspace = NULL; + mpi_size_t tsize=0; /* to avoid compiler warning */ + /* fixme: we should check that the warning is void*/ + + esize = exponent->nlimbs; + msize = mod->nlimbs; + size = 2 * msize; + esign = exponent->sign; + msign = mod->sign; + + esec = mpi_is_secure(exponent); + msec = mpi_is_secure(mod); + bsec = mpi_is_secure(base); + rsec = mpi_is_secure(res); + + rp = res->d; + ep = exponent->d; + + if( !msize ) + msize = 1 / msize; /* provoke a signal */ + + if( !esize ) { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + * depending on if MOD equals 1. */ + rp[0] = 1; + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + res->sign = 0; + goto leave; + } + + /* Normalize MOD (i.e. make its most significant bit set) as required by + * mpn_divrem. This will make the intermediate values in the calculation + * slightly larger, but the correct result is obtained after a final + * reduction using the original MOD value. */ + mp = mp_marker = mpi_alloc_limb_space(msize, msec); + count_leading_zeros( mod_shift_cnt, mod->d[msize-1] ); + if( mod_shift_cnt ) + mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt ); + else + MPN_COPY( mp, mod->d, msize ); + + bsize = base->nlimbs; + bsign = base->sign; + if( bsize > msize ) { /* The base is larger than the module. Reduce it. */ + /* Allocate (BSIZE + 1) with space for remainder and quotient. + * (The quotient is (bsize - msize + 1) limbs.) */ + bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); + MPN_COPY( bp, base->d, bsize ); + /* We don't care about the quotient, store it above the remainder, + * at BP + MSIZE. */ + mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize ); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + * quite a few times. */ + MPN_NORMALIZE( bp, bsize ); + } + else + bp = base->d; + + if( !bsize ) { + res->nlimbs = 0; + res->sign = 0; + goto leave; + } + + if( res->alloced < size ) { + /* We have to allocate more space for RES. If any of the input + * parameters are identical to RES, defer deallocation of the old + * space. */ + if( rp == ep || rp == mp || rp == bp ) { + rp = mpi_alloc_limb_space( size, rsec ); + assign_rp = 1; + } + else { + mpi_resize( res, size ); + rp = res->d; + } + } + else { /* Make BASE, EXPONENT and MOD not overlap with RES. */ + if( rp == bp ) { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + assert( !bp_marker ); + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); + } + if( rp == ep ) { + /* RES and EXPONENT are identical. + Allocate temp. space for EXPONENT. */ + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if( rp == mp ) { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ + assert( !mp_marker ); + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + } + + MPN_COPY( rp, bp, bsize ); + rsize = bsize; + rsign = bsign; + + { + mpi_size_t i; + mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); + int c; + mpi_limb_t e; + mpi_limb_t carry_limb; + struct karatsuba_ctx karactx; + + memset( &karactx, 0, sizeof karactx ); + negative_result = (ep[0] & 1) && base->sign; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MPI_LIMB - 1 - c; + + /* Main loop. + * + * Make the result be pointed to alternately by XP and RP. This + * helps us avoid block copying, which would otherwise be necessary + * with the overlap restrictions of mpihelp_divmod. With 50% probability + * the result after this loop will be in the area originally pointed + * by RP (==RES->d), and with 50% probability in the area originally + * pointed to by XP. + */ + + for(;;) { + while( c ) { + mpi_ptr_t tp; + mpi_size_t xsize; + + /*mpihelp_mul_n(xp, rp, rp, rsize);*/ + if( rsize < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( xp, rp, rsize ); + else { + if( !tspace ) { + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + else if( tsize < (2*rsize) ) { + mpi_free_limb_space( tspace ); + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + mpih_sqr_n( xp, rp, rsize, tspace ); + } + + xsize = 2 * rsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + if( (mpi_limb_signed_t)e < 0 ) { + /*mpihelp_mul( xp, rp, rsize, bp, bsize );*/ + if( bsize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( xp, rp, rsize, bp, bsize ); + } + else { + mpihelp_mul_karatsuba_case( + xp, rp, rsize, bp, bsize, &karactx ); + } + + xsize = rsize + bsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if( i < 0 ) + break; + e = ep[i]; + c = BITS_PER_MPI_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT + * steps. Adjust the result by reducing it with the original MOD. + * + * Also make sure the result is put in RES->d (where it already + * might be, see above). + */ + if( mod_shift_cnt ) { + carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if( carry_limb ) { + rp[rsize] = carry_limb; + rsize++; + } + } + else { + MPN_COPY( res->d, rp, rsize); + rp = res->d; + } + + if( rsize >= msize ) { + mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if( mod_shift_cnt ) + mpihelp_rshift( rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + + mpihelp_release_karatsuba_ctx( &karactx ); + } + + if( negative_result && rsize ) { + if( mod_shift_cnt ) + mpihelp_rshift( mp, mp, msize, mod_shift_cnt); + mpihelp_sub( rp, mp, msize, rp, rsize); + rsize = msize; + rsign = msign; + MPN_NORMALIZE(rp, rsize); + } + res->nlimbs = rsize; + res->sign = rsign; + + leave: + if( assign_rp ) mpi_assign_limb_space( res, rp, size ); + if( mp_marker ) mpi_free_limb_space( mp_marker ); + if( bp_marker ) mpi_free_limb_space( bp_marker ); + if( ep_marker ) mpi_free_limb_space( ep_marker ); + if( xp_marker ) mpi_free_limb_space( xp_marker ); + if( tspace ) mpi_free_limb_space( tspace ); +} + diff -uNr a/smg_comms/mpi/mpi-scan.c b/smg_comms/mpi/mpi-scan.c --- a/smg_comms/mpi/mpi-scan.c false +++ b/smg_comms/mpi/mpi-scan.c eaf2827058a07c1502ea5da210ae7b7662b6b02ac4847d37467fb498ddb84d592cce814db4b15588da8c5349e4ffe4636d267fedf0eceb29e63bd8dcf0249be2 @@ -0,0 +1,56 @@ +/* mpi-scan.c - MPI functions + * Modified by No Such Labs. (C) 2015. See README. + * Modified by S.MG 2017 (removed code that is not used by eucrypt and at the same time so ugly it needs rewrite anyway) + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +/**************** + * Count the number of zerobits at the low end of A + * This is used currently by eucrypt's primality tests. + */ +unsigned int +mpi_trailing_zeros( MPI a ) +{ + unsigned n, count = 0; + + for(n=0; n < a->nlimbs; n++ ) { + if( a->d[n] ) { + unsigned nn; + mpi_limb_t alimb = a->d[n]; + + count_trailing_zeros( nn, alimb ); + count += nn; + break; + } + count += BITS_PER_MPI_LIMB; + } + return count; + +} + + diff -uNr a/smg_comms/mpi/mpi.gpr b/smg_comms/mpi/mpi.gpr --- a/smg_comms/mpi/mpi.gpr false +++ b/smg_comms/mpi/mpi.gpr 9f5e8e039129a65969e8e89ed17dfa033676d406e8e872fd9f47fac0bc207acce55201d257671b39e46dc90909109588398005f5db9b1fda3cdf3a97cf434f99 @@ -0,0 +1,13 @@ +-- S.MG, 2018 + +project MPI is + for Languages use ("C"); + for Library_Name use "MPI"; + for Library_Kind use "static"; + + for Source_Dirs use (".", "include"); + for Object_Dir use "obj"; + for Library_Dir use "bin"; + +end MPI; + diff -uNr a/smg_comms/mpi/mpicoder.c b/smg_comms/mpi/mpicoder.c --- a/smg_comms/mpi/mpicoder.c false +++ b/smg_comms/mpi/mpicoder.c e415fde563a94473cfe9e85e8862cf30f6c8b820f383f6a964aef675e576648bc9f66f55ba7ef01e27969fe57d14293b96daac1525197be392abb5c9b1ad4040 @@ -0,0 +1,347 @@ +/* mpicoder.c - Coder for the external representation of MPIs + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "knobs.h" +#include "mpi.h" +#include "mpi-internal.h" +#include "memory.h" +#include "util.h" + +#ifdef M_DEBUG +#undef mpi_read +#endif + +#define MAX_EXTERN_MPI_BITS 16384 + + +MPI +mpi_read_from_buffer(byte *buffer, unsigned int *ret_nread, int secure) +{ + int i, j; + unsigned nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + MPI val = NULL; + + if( *ret_nread < 2 ) + goto leave; + nbits = buffer[0] << 8 | buffer[1]; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_info ("mpi too large (%u bits)\n", nbits); + goto leave; + } + buffer += 2; + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + val = secure? mpi_alloc_secure( nlimbs ) + : mpi_alloc( nlimbs ); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + val->nbits = nbits; + j= val->nlimbs = nlimbs; + val->sign = 0; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + if( ++nread > *ret_nread ) { + /* This (as well as the above error condition) may + happen if we use this function to parse a decrypted + MPI which didn't turn out to be a real MPI - possible + because the supplied key was wrong but the OpenPGP + checksum didn't caught it. */ + log_info ("mpi larger than buffer\n"); + mpi_free (val); + val = NULL; + goto leave; + } + a <<= 8; + a |= *buffer++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + *ret_nread = nread; + return val; +} + + +/**************** + * Make an mpi from a character string. + */ +int +mpi_fromstr(MPI val, const char *str) +{ + int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2; + unsigned nbits, nbytes, nlimbs; + mpi_limb_t a; + + if( *str == '-' ) { + sign = 1; + str++; + } + if( *str == '0' && str[1] == 'x' ) + hexmode = 1; + else + return 1; /* other bases are not yet supported */ + str += 2; + + nbits = strlen(str)*4; + if( nbits % 8 ) + prepend_zero = 1; + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + if( val->alloced < nlimbs ) + mpi_resize(val, nlimbs ); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + j= val->nlimbs = nlimbs; + val->sign = sign; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + if( prepend_zero ) { + c1 = '0'; + prepend_zero = 0; + } + else + c1 = *str++; + assert(c1); + c2 = *str++; + assert(c2); + if( c1 >= '0' && c1 <= '9' ) + c = c1 - '0'; + else if( c1 >= 'a' && c1 <= 'f' ) + c = c1 - 'a' + 10; + else if( c1 >= 'A' && c1 <= 'F' ) + c = c1 - 'A' + 10; + else { + mpi_clear(val); + return 1; + } + c <<= 4; + if( c2 >= '0' && c2 <= '9' ) + c |= c2 - '0'; + else if( c2 >= 'a' && c2 <= 'f' ) + c |= c2 - 'a' + 10; + else if( c2 >= 'A' && c2 <= 'F' ) + c |= c2 - 'A' + 10; + else { + mpi_clear(val); + return 1; + } + a <<= 8; + a |= c; + } + i = 0; + val->d[j-1] = a; + } + + return 0; +} + + +/**************** + * print an MPI to the given stream and return the number of characters + * printed. + */ +int +mpi_print( FILE *fp, MPI a, int mode ) +{ + int i, n=0; + + if( a == NULL ) + return fprintf(fp, "[MPI_NULL]"); + if( !mode ) { + unsigned int n1; + + n1 = mpi_get_nbits(a); + n += fprintf(fp, "[%u bits]", n1); + } + else { + if( a->sign ) + putc('-', fp); +#if BYTES_PER_MPI_LIMB == 2 +#define X "4" +#elif BYTES_PER_MPI_LIMB == 4 +#define X "8" +#elif BYTES_PER_MPI_LIMB == 8 +#define X "16" +#else +#error please define the format here +#endif + for(i=a->nlimbs; i > 0 ; i-- ) { + n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); +#undef X + } + if( !a->nlimbs ) + putc('0', fp ); + } + return n; +} + + +/* +void +g10_log_mpidump( const char *text, MPI a ) +{ + FILE *fp = log_stream(); + + g10_log_print_prefix(text); + mpi_print(fp, a, 1 ); + fputc('\n', fp); +} +*/ + + +/**************** + * Return an xmalloced buffer with the MPI (msb first). + * NBYTES receives the length of this buffer. Caller must free the + * return string (This function does return a 0 byte buffer with NBYTES + * set to zero if the value of A is zero. If sign is not NULL, it will + * be set to the sign of the A. + */ +static byte * +do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure ) +{ + byte *p, *buffer; + mpi_limb_t alimb; + int i; + unsigned int n; + + if( sign ) + *sign = a->sign; + *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB; + if (!n) + n++; /* avoid zero length allocation */ + p = buffer = force_secure || mpi_is_secure(a) ? xmalloc_secure(n) + : xmalloc(n); + + for(i=a->nlimbs-1; i >= 0; i-- ) { + alimb = a->d[i]; +#if BYTES_PER_MPI_LIMB == 4 + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#elif BYTES_PER_MPI_LIMB == 8 + *p++ = alimb >> 56; + *p++ = alimb >> 48; + *p++ = alimb >> 40; + *p++ = alimb >> 32; + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#else +#error please implement for this limb size. +#endif + } + + /* this is sub-optimal but we need to do the shift operation + * because the caller has to free the returned buffer */ + for(p=buffer; !*p && *nbytes; p++, --*nbytes ) + ; + if( p != buffer ) + memmove(buffer,p, *nbytes); + + return buffer; +} + + +byte * +mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ) +{ + return do_get_buffer( a, nbytes, sign, 0 ); +} + +byte * +mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ) +{ + return do_get_buffer( a, nbytes, sign, 1 ); +} + +/**************** + * Use BUFFER to update MPI. + */ +void +mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ) +{ + const byte *p; + mpi_limb_t alimb; + int nlimbs; + int i; + + nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; + RESIZE_IF_NEEDED(a, nlimbs); + a->sign = sign; + + for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) { +#if BYTES_PER_MPI_LIMB == 4 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; + alimb |= (mpi_limb_t)*p-- << 32 ; + alimb |= (mpi_limb_t)*p-- << 40 ; + alimb |= (mpi_limb_t)*p-- << 48 ; + alimb |= (mpi_limb_t)*p-- << 56 ; +#else +#error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + if( p >= buffer ) { +#if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ; +#else +#error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + a->nlimbs = i; + assert( i == nlimbs ); +} diff -uNr a/smg_comms/mpi/mpih-add1.c b/smg_comms/mpi/mpih-add1.c --- a/smg_comms/mpi/mpih-add1.c false +++ b/smg_comms/mpi/mpih-add1.c b5713900ed6f31370c3136b3bebc4a96603a0f319d1e75abd706219bd6fdd5c5105f9e33275df06abd1321552ffc342dcf41c15cc28873faee616a0d62974467 @@ -0,0 +1,59 @@ +/* mpihelp-add_1.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + diff -uNr a/smg_comms/mpi/mpih-cmp.c b/smg_comms/mpi/mpih-cmp.c --- a/smg_comms/mpi/mpih-cmp.c false +++ b/smg_comms/mpi/mpih-cmp.c e789cea1e3a670f80f48773ae523b6ba57fa5bdbc170d552037871c9e22f04bc697ed636c9dcc13bdaf1ddc7e86748cee33cf8519f619e8e6f7f4486a549c881 @@ -0,0 +1,55 @@ +/* mpihelp-sub.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + +/**************** + * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + * There are no restrictions on the relative sizes of + * the two arguments. + * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. + */ +int +mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t op1_word, op2_word; + + for( i = size - 1; i >= 0 ; i--) { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if( op1_word != op2_word ) + goto diff; + } + return 0; + + diff: + /* This can *not* be simplified to + * op2_word - op2_word + * since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} + diff -uNr a/smg_comms/mpi/mpih-div.c b/smg_comms/mpi/mpih-div.c --- a/smg_comms/mpi/mpih-div.c false +++ b/smg_comms/mpi/mpih-div.c 49ef731356e9c2e54d04cb0f5c4a68285ad1ca1c27015aacefda5f0cb5ac676a0dc47b1656ab2057e1cffcc58e837b1010e85391a8f570ccdda24630b28620f7 @@ -0,0 +1,529 @@ +/* mpihelp-div.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + * here (not udiv_qrnnd). + */ + +mpi_limb_t +mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV(dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + i--; + + for( ; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if( UDIV_NEEDS_NORMALIZATION ) { + int normalization_steps; + + count_leading_zeros(normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for(i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + i--; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + * the NSIZE-DSIZE least significant quotient limbs at QP + * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + * non-zero, generate that many fraction bits and append them after the + * other quotient limbs. + * Return the most significant limb of the quotient, this is always 0 or 1. + * + * Preconditions: + * 0. NSIZE >= DSIZE. + * 1. The most significant bit of the divisor must be set. + * 2. QP must either not overlap with the input operands at all, or + * QP + DSIZE >= NP must hold true. (This means that it's + * possible to put the quotient in the high part of NUM, right after the + * remainder in NUM. + * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. + */ + +mpi_limb_t +mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize) +{ + mpi_limb_t most_significant_q_limb = 0; + + switch(dsize) { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + return 1 / dsize; + + case 1: + { + mpi_size_t i; + mpi_limb_t n1; + mpi_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if( n1 >= d ) { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for( i = nsize - 2; i >= 0; i--) + udiv_qrnnd( qp[i], n1, n1, np[i], d ); + qp -= qextra_limbs; + + for( i = qextra_limbs - 1; i >= 0; i-- ) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mpi_size_t i; + mpi_limb_t n1, n0, n2; + mpi_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { + mpi_limb_t q; + mpi_limb_t r; + + if( i >= qextra_limbs ) + np--; + else + np[0] = 0; + + if( n1 == d1 ) { + /* Q should be either 111..111 or 111..110. Need special + * treatment of this rare case as normal division would + * give overflow. */ + q = ~(mpi_limb_t)0; + + r = n0 + d1; + if( r < d1 ) { /* Carry in the addition? */ + add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0?1:0); + n0 = -d0; + } + else { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if( n1 > r || (n1 == r && n0 > n2) ) { + /* The estimated Q was too large. */ + q--; + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if( r >= d1 ) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mpi_size_t i; + mpi_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if( n0 >= dX ) { + if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) { + mpihelp_sub_n(np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { + mpi_limb_t q; + mpi_limb_t n1, n2; + mpi_limb_t cy_limb; + + if( i >= qextra_limbs ) { + np--; + n2 = np[dsize]; + } + else { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize - 1); + np[0] = 0; + } + + if( n0 == dX ) { + /* This might over-estimate q, but it's probably not worth + * the extra code here to find out. */ + q = ~(mpi_limb_t)0; + } + else { + mpi_limb_t r; + + udiv_qrnnd(q, r, n0, np[dsize - 1], dX); + umul_ppmm(n1, n0, d1, q); + + while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { + q--; + r += dX; + if( r < dX ) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + * after the calculation of q. Taking advantage of that, we + * could make this loop make two iterations less. */ + cy_limb = mpihelp_submul_1(np, dp, dsize, q); + + if( n2 != cy_limb ) { + mpihelp_add_n(np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} + + +/**************** + * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + * Return the single-limb remainder. + * There are no constraints on the value of the divisor. + * + * QUOT_PTR and DIVIDEND_PTR might point to the same limb. + */ + +mpi_limb_t +mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV( quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t) 0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + quot_ptr[i--] = 0; + + for( ; i >= 0; i-- ) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if(UDIV_NEEDS_NORMALIZATION) { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + quot_ptr[i--] = 0; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); + } + return r; + } +} diff -uNr a/smg_comms/mpi/mpih-lshift.c b/smg_comms/mpi/mpih-lshift.c --- a/smg_comms/mpi/mpih-lshift.c false +++ b/smg_comms/mpi/mpih-lshift.c b4153b7f9f829152ca1273195628566628ca4eed54792c61cd58ec4481f83cded7e0a6dd4e1fb632b10b20314b28a209d2cf1f78a684a64f7a9002b6e00fb2b9 @@ -0,0 +1,64 @@ +/* mpihelp-lshift.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while( --i >= 0 ) { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff -uNr a/smg_comms/mpi/mpih-mul.c b/smg_comms/mpi/mpih-mul.c --- a/smg_comms/mpi/mpih-mul.c false +++ b/smg_comms/mpi/mpih-mul.c 1c5bd39c13569d58a5cfd542d96df998b63efd14edfcdb9488975b69dd7796b21ef656577e9da950cece9d9122b7030395f0714cbba2983b3dafc860b34c1b85 @@ -0,0 +1,519 @@ +/* mpihelp-mul.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + mpih_sqr_n_basecase (prodp, up, size); \ + else \ + mpih_sqr_n (prodp, up, size, tspace); \ + } while (0); + + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + * always stored. Return the most significant limb. + * + * Argument constraints: + * 1. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + * + * + * Handle simple cases with traditional multiplication. + * + * This is the most critical code of multiplication. All multiplies rely + * on this, both small and huge. Small ones arrive here immediately. Huge + * ones arrive here as this is the base case for Karatsuba's recursive + * algorithm below. + */ + +static mpi_limb_t +mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, + mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t cy; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO( prodp, size ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < size; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy; + prodp++; + } + + return cy; +} + + +static void +mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size, mpi_ptr_t tspace ) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] ); + prodp[esize + size] = cy_limb; + } + else { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + * + * Split U in two pieces, U1 and U0, such that + * U = U0 + U1*(B**n), + * and V in V1 and V0, such that + * V = V0 + V1*(B**n). + * + * UV is then computed recursively using the identity + * + * 2n n n n + * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + * 1 1 1 0 0 1 0 0 + * + * Where B = 2**BITS_PER_MP_LIMB. + */ + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + int negflg; + + /* Product H. ________________ ________________ + * |_____U1 x V1____||____U0 x V0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(V0-V1)_| + */ + if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) { + mpihelp_sub_n(prodp, up + hsize, up, hsize); + negflg = 0; + } + else { + mpihelp_sub_n(prodp, up, up + hsize, hsize); + negflg = 1; + } + if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) { + mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else { + mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); + + /* Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n( prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number) */ + if(negflg) + cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size); + else + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x V0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); + + /* Add/copy Product L (twice) */ + + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1(prodp + size, prodp + size, size, 1); + } +} + + +void +mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t cy_limb; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO(prodp, size); + cy_limb = 0; + } + else + cy_limb = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i=1; i < size; i++) { + v_limb = up[i]; + if( v_limb <= 1 ) { + cy_limb = 0; + if( v_limb == 1 ) + cy_limb = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + + +void +mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] ); + + prodp[esize + size] = cy_limb; + } + else { + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + + /* Product H. ________________ ________________ + * |_____U1 x U1____||____U0 x U0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(U0-U1)_| + */ + if( mpihelp_cmp( up + hsize, up, hsize) >= 0 ) + mpihelp_sub_n( prodp, up + hsize, up, hsize); + else + mpihelp_sub_n (prodp, up, up + hsize, hsize); + + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); + + /* Add/copy product H */ + MPN_COPY(prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n(prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number). */ + cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x U0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /* Add/copy Product L (twice). */ + cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, + hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1 (prodp + size, prodp + size, size, 1); + } +} + + +/* This should be made into an inline function in gmp.h. */ +void +mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + int secure; + + if( up == vp ) { + if( size < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( prodp, up, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mpih_sqr_n( prodp, up, size, tspace ); + mpi_free_limb_space( tspace ); + } + } + else { + if( size < KARATSUBA_THRESHOLD ) + mul_n_basecase( prodp, up, vp, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ) || m_is_secure( vp ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mul_n (prodp, up, vp, size, tspace); + mpi_free_limb_space( tspace ); + } + } +} + + + +void +mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ) +{ + mpi_limb_t cy; + + if( !ctx->tspace || ctx->tspace_size < vsize ) { + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + ctx->tspace = mpi_alloc_limb_space( 2 * vsize, + m_is_secure( up ) || m_is_secure( vp ) ); + ctx->tspace_size = vsize; + } + + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + if( !ctx->tp || ctx->tp_size < vsize ) { + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + ctx->tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up ) + || m_is_secure( vp ) ); + ctx->tp_size = vsize; + } + + do { + MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); + cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize ); + mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + } + + if( usize ) { + if( usize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( ctx->tspace, vp, vsize, up, usize ); + } + else { + if( !ctx->next ) { + ctx->next = xmalloc_clear( sizeof *ctx ); + } + mpihelp_mul_karatsuba_case( ctx->tspace, + vp, vsize, + up, usize, + ctx->next ); + } + + cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize); + mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); + } +} + + +void +mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) +{ + struct karatsuba_ctx *ctx2; + + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + for( ctx=ctx->next; ctx; ctx = ctx2 ) { + ctx2 = ctx->next; + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + xfree( ctx ); + } +} + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + * and v (pointed to by VP, with VSIZE limbs), and store the result at + * PRODP. USIZE + VSIZE limbs are always stored, but if the input + * operands are normalized. Return the most significant limb of the + * result. + * + * NOTE: The space pointed to by PRODP is overwritten before finished + * with U and V, so overlap is an error. + * + * Argument constraints: + * 1. USIZE >= VSIZE. + * 2. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + */ + +mpi_limb_t +mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize) +{ + mpi_ptr_t prod_endp = prodp + usize + vsize - 1; + mpi_limb_t cy; + struct karatsuba_ctx ctx; + + if( vsize < KARATSUBA_THRESHOLD ) { + mpi_size_t i; + mpi_limb_t v_limb; + + if( !vsize ) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, usize ); + else + MPN_ZERO( prodp, usize ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, usize, v_limb ); + + prodp[usize] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < vsize; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, usize); + } + else + cy = mpihelp_addmul_1(prodp, up, usize, v_limb); + + prodp[usize] = cy; + prodp++; + } + + return cy; + } + + memset( &ctx, 0, sizeof ctx ); + mpihelp_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); + mpihelp_release_karatsuba_ctx( &ctx ); + return *prod_endp; +} + + diff -uNr a/smg_comms/mpi/mpih-mul1.c b/smg_comms/mpi/mpih-mul1.c --- a/smg_comms/mpi/mpih-mul1.c false +++ b/smg_comms/mpi/mpih-mul1.c 2fcc124504adc576636a56bc387f7f6b73c60b263ed01a7dffa2c2131f89aa6d337399ef9db92c5423d25ba596a898ad1160ac1eab5d49768aeab14d08c29466 @@ -0,0 +1,56 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + diff -uNr a/smg_comms/mpi/mpih-mul2.c b/smg_comms/mpi/mpih-mul2.c --- a/smg_comms/mpi/mpih-mul2.c false +++ b/smg_comms/mpi/mpih-mul2.c 3b4cc6335137ae38d7a62b34e1d2319c33371d77b6169ab101b4df8ce83ee7e10ff859f24626b13ae42aff8cffc805ffaa433d53faf56c5924837ac1fac0a6f9 @@ -0,0 +1,61 @@ +/* mpihelp-mul_2.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } while ( ++j ); + return cy_limb; +} + + diff -uNr a/smg_comms/mpi/mpih-mul3.c b/smg_comms/mpi/mpih-mul3.c --- a/smg_comms/mpi/mpih-mul3.c false +++ b/smg_comms/mpi/mpih-mul3.c a6703d0851fb4f5a7c05ea94b0ea1c9df3b79379b43c55ef10481496984dc6b58c3b26fc009607ede37917758cc7576065049c5a511eee7e0b9048e1a1b06654 @@ -0,0 +1,62 @@ +/* mpihelp-mul_3.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + + diff -uNr a/smg_comms/mpi/mpih-rshift.c b/smg_comms/mpi/mpih-rshift.c --- a/smg_comms/mpi/mpih-rshift.c false +++ b/smg_comms/mpi/mpih-rshift.c fb51d6b55d5e9b7ada61ce8c50c3958a5d8b38cd1673683437d572ef52469c428a68c2926739eee75ef379db77c713f4bd8506b53a7e259e2ce9516e23ac44ef @@ -0,0 +1,62 @@ +/* mpih-rshift.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for( i=1; i < usize; i++) { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff -uNr a/smg_comms/mpi/mpih-sub1.c b/smg_comms/mpi/mpih-sub1.c --- a/smg_comms/mpi/mpih-sub1.c false +++ b/smg_comms/mpi/mpih-sub1.c 88c8dfd8a7cbbc742fe8e01121c9166dc010ba16554277137ece7642bb6c9d94183ea6d23f4118d2bcd7a2a31a399a22a7a264ea178c0ce0bd4a2d0bf18f149f @@ -0,0 +1,60 @@ +/* mpihelp-add_2.c - MPI helper functions + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "knobs.h" +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + + diff -uNr a/smg_comms/mpi/mpiutil.c b/smg_comms/mpi/mpiutil.c --- a/smg_comms/mpi/mpiutil.c false +++ b/smg_comms/mpi/mpiutil.c d98f0266d7c1f2466393e4951babe3a7289cf8133821fbaf3bd139383aa5e14fc1cdab87c6329ab6790b250ce9f141b2b7f935804ec43bc5a4933a2932a8178b @@ -0,0 +1,517 @@ +/* mpiutil.ac - Utility functions for MPI + * Modified by No Such Labs. (C) 2015. See README. + * Modified by S.MG, 2018. Added mpi_get_alloced(MPI a) + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "knobs.h" +#include "mpi.h" +#include "mpi-internal.h" +#include "memory.h" +#include "util.h" + + +#ifdef M_DEBUG +#undef mpi_alloc +#undef mpi_alloc_secure +#undef mpi_free +#endif + +/**************** + * Note: It was a bad idea to use the number of limbs to allocate + * because on a alpha the limbs are large but we normally need + * integers of n bits - So we should chnage this to bits (or bytes). + * + * But mpi_alloc is used in a lot of places :-) + */ +MPI +#ifdef M_DEBUG +mpi_debug_alloc( unsigned nlimbs, const char *info ) +#else +mpi_alloc( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); +#ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL; +#else + a = xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; +#endif + a->alloced = nlimbs; + a->nlimbs = 0; + a->sign = 0; + a->flags = 0; + a->nbits = 0; + return a; +} + +void +mpi_m_check( MPI a ) +{ + m_check(a); + m_check(a->d); +} + +MPI +#ifdef M_DEBUG +mpi_debug_alloc_secure( unsigned nlimbs, const char *info ) +#else +mpi_alloc_secure( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); +#ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL; +#else + a = xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; +#endif + a->alloced = nlimbs; + a->flags = 1; + a->nlimbs = 0; + a->sign = 0; + a->nbits = 0; + return a; +} + + +#if 0 +static void *unused_limbs_5; +static void *unused_limbs_32; +static void *unused_limbs_64; +#endif + +mpi_ptr_t +#ifdef M_DEBUG +mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info ) +#else +mpi_alloc_limb_space( unsigned nlimbs, int secure ) +#endif +{ + size_t len = nlimbs * sizeof(mpi_limb_t); + mpi_ptr_t p; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 ); +#if 0 + if( !secure ) { + if( nlimbs == 5 && unused_limbs_5 ) { /* DSA 160 bits */ + p = unused_limbs_5; + unused_limbs_5 = *p; + return p; + } + else if( nlimbs == 32 && unused_limbs_32 ) { /* DSA 1024 bits */ + p = unused_limbs_32; + unused_limbs_32 = *p; + return p; + } + else if( nlimbs == 64 && unused_limbs_64 ) { /* DSA 2*1024 bits */ + p = unused_limbs_64; + unused_limbs_64 = *p; + return p; + } + } +#endif + +#ifdef M_DEBUG + p = secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info ); +#else + p = secure? xmalloc_secure( len ):xmalloc( len ); +#endif + + return p; +} + +void +#ifdef M_DEBUG +mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ) +#else +mpi_free_limb_space( mpi_ptr_t a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 ); + +#if 0 + if( !m_is_secure(a) ) { + size_t nlimbs = m_size(a) / 4 ; + void *p = a; + + if( nlimbs == 5 ) { /* DSA 160 bits */ + *a = unused_limbs_5; + unused_limbs_5 = a; + return; + } + else if( nlimbs == 32 ) { /* DSA 1024 bits */ + *a = unused_limbs_32; + unused_limbs_32 = a; + return; + } + else if( nlimbs == 64 ) { /* DSA 2*1024 bits */ + *a = unused_limbs_64; + unused_limbs_64 = a; + return; + } + } +#endif + + xfree(a); +} + + +void +mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ) +{ + mpi_free_limb_space(a->d); + a->d = ap; + a->alloced = nlimbs; +} + + + +/**************** + * Resize the array of A to NLIMBS. the additional space is cleared + * (set to 0) [done by xrealloc()] + */ +void +#ifdef M_DEBUG +mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ) +#else +mpi_resize( MPI a, unsigned nlimbs ) +#endif +{ + if( nlimbs <= a->alloced ) + return; /* no need to do it */ + /* Note: a->secure is not used - instead the realloc functions + * take care of it. Maybe we should drop a->secure completely + * and rely on a mpi_is_secure function, which would be + * a wrapper around m_is_secure + */ +#ifdef M_DEBUG + if( a->d ) + a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info ); + else + a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info ); +#else + if( a->d ) + a->d = xrealloc(a->d, nlimbs * sizeof(mpi_limb_t) ); + else + a->d = xmalloc_clear( nlimbs * sizeof(mpi_limb_t) ); +#endif + a->alloced = nlimbs; +} + +void +mpi_clear( MPI a ) +{ + a->nlimbs = 0; + a->nbits = 0; + a->flags = 0; +} + + +void +#ifdef M_DEBUG +mpi_debug_free( MPI a, const char *info ) +#else +mpi_free( MPI a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free\n" ); + if( a->flags & 4 ) + xfree( a->d ); + else { +#ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, info); +#else + mpi_free_limb_space(a->d); +#endif + } + if( a->flags & ~7 ) + log_bug("invalid flag value in mpi\n"); + xfree(a); +} + + +void +mpi_set_secure( MPI a ) +{ + mpi_ptr_t ap, bp; + + if( (a->flags & 1) ) + return; + a->flags |= 1; + ap = a->d; + if( !a->nlimbs ) { + assert(!ap); + return; + } +#ifdef M_DEBUG + bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" ); +#else + bp = mpi_alloc_limb_space( a->nlimbs, 1 ); +#endif + MPN_COPY( bp, ap, a->nlimbs ); + a->d = bp; +#ifdef M_DEBUG + mpi_debug_free_limb_space(ap, "set_secure"); +#else + mpi_free_limb_space(ap); +#endif +} + + +MPI +mpi_set_opaque( MPI a, void *p, unsigned int len ) +{ + if( !a ) { +#ifdef M_DEBUG + a = mpi_debug_alloc(0,"alloc_opaque"); +#else + a = mpi_alloc(0); +#endif + } + + if( a->flags & 4 ) + xfree( a->d ); + else { +#ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, "alloc_opaque"); +#else + mpi_free_limb_space(a->d); +#endif + } + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->nbits = len; + a->flags = 4; + return a; +} + + +void * +mpi_get_opaque( MPI a, unsigned int *len ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( len ) + *len = a->nbits; + return a->d; +} + + +/**************** + * Note: This copy function should not interpret the MPI + * but copy it transparently. + */ +MPI +#ifdef M_DEBUG +mpi_debug_copy( MPI a, const char *info ) +#else +mpi_copy( MPI a ) +#endif +{ + int i; + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits ) + : xmalloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { +#ifdef M_DEBUG + b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) + : mpi_debug_alloc( a->nlimbs, info ); +#else + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); +#endif + b->nlimbs = a->nlimbs; + b->sign = a->sign; + b->flags = a->flags; + b->nbits = a->nbits; + for(i=0; i < b->nlimbs; i++ ) + b->d[i] = a->d[i]; + } + else + b = NULL; + return b; +} + + +/**************** + * This function allocates an MPI which is optimized to hold + * a value as large as the one given in the argument and allocates it + * with the same flags as A. + */ +MPI +#ifdef M_DEBUG +mpi_debug_alloc_like( MPI a, const char *info ) +#else +mpi_alloc_like( MPI a ) +#endif +{ + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits ) + : xmalloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { +#ifdef M_DEBUG + b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) + : mpi_debug_alloc( a->nlimbs, info ); +#else + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); +#endif + b->nlimbs = 0; + b->sign = 0; + b->flags = a->flags; + b->nbits = 0; + } + else + b = NULL; + return b; +} + + +void +mpi_set( MPI w, MPI u) +{ + mpi_ptr_t wp, up; + mpi_size_t usize = u->nlimbs; + int usign = u->sign; + + RESIZE_IF_NEEDED(w, usize); + wp = w->d; + up = u->d; + MPN_COPY( wp, up, usize ); + w->nlimbs = usize; + w->nbits = u->nbits; + w->flags = u->flags; + w->sign = usign; +} + + +void +mpi_set_ui( MPI w, unsigned long u) +{ + RESIZE_IF_NEEDED(w, 1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + w->nbits = 0; + w->flags = 0; +} + + +MPI +mpi_alloc_set_ui( unsigned long u) +{ +#ifdef M_DEBUG + MPI w = mpi_debug_alloc(1,"alloc_set_ui"); +#else + MPI w = mpi_alloc(1); +#endif + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + return w; +} + + +void +mpi_swap( MPI a, MPI b) +{ + struct gcry_mpi tmp; + + tmp = *a; *a = *b; *b = tmp; +} + + +int +mpi_get_nlimbs (MPI a) +{ + return a->nlimbs; +} + +/* + * Returns the allocated space for the given MPI, as number of limbs. + */ +int +mpi_get_alloced (MPI a) +{ + return a->alloced; +} + +int +mpi_is_neg (MPI a) +{ + return a->sign; +} + + +/* Return the number of limbs to store an MPI which is specified by + the number of bytes to represent it. */ +unsigned int +mpi_nlimb_hint_from_nbytes (unsigned int nbytes) +{ + return (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; +} + +/* Return the number of limbs to store an MPI which is specified by + the number of bytes to represent it. */ +unsigned int +mpi_nlimb_hint_from_nbits (unsigned int nbits) +{ + return (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB; +} + +unsigned int +mpi_get_flags (MPI a) +{ + return a->flags; +} diff -uNr a/smg_comms/mpi/obj/README b/smg_comms/mpi/obj/README --- a/smg_comms/mpi/obj/README false +++ b/smg_comms/mpi/obj/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/mpi/secmem.c b/smg_comms/mpi/secmem.c --- a/smg_comms/mpi/secmem.c false +++ b/smg_comms/mpi/secmem.c 2b787a241ab819008b23b6235aec68ea7ea5dc092859ff42ffe50a7bd00d710f39547e35ee66449377fe70bdd870f7bd4b40b7ede228f6842671c5e167183493 @@ -0,0 +1,511 @@ +/* secmem.c - memory allocation from a secure heap + * Modified by No Such Labs. (C) 2015. See README. + * + * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10, + * SHA256(gnupg-1.4.10.tar.gz): + * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a + * (C) 1994-2005 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "knobs.h" + +#include +#include +#include +#include +#include +#include +#if defined(HAVE_MLOCK) || defined(HAVE_MMAP) +#include +#include +#include +#ifdef USE_CAPABILITIES +#include +#endif +#ifdef HAVE_PLOCK +#include +#endif +#endif + +#include "types.h" +#include "memory.h" +#include "util.h" + +/* MinGW doesn't seem to prototype getpagesize, though it does have + it. */ +#if !HAVE_DECL_GETPAGESIZE +int getpagesize(void); +#endif + +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif +/* It seems that Slackware 7.1 does not know about EPERM */ +#if !defined(EPERM) && defined(ENOMEM) +#define EPERM ENOMEM +#endif + + +#define DEFAULT_POOLSIZE 16384 + +typedef struct memblock_struct MEMBLOCK; +struct memblock_struct { + unsigned size; + union { + MEMBLOCK *next; + PROPERLY_ALIGNED_TYPE aligned; + } u; +}; + + + +static void *pool; +static volatile int pool_okay; /* may be checked in an atexit function */ +#ifdef HAVE_MMAP +static volatile int pool_is_mmapped; +#endif +static size_t poolsize; /* allocated length */ +static size_t poollen; /* used length */ +static MEMBLOCK *unused_blocks; +static unsigned max_alloced; +static unsigned cur_alloced; +static unsigned max_blocks; +static unsigned cur_blocks; +static int disable_secmem; +static int show_warning; +static int no_warning; +static int suspend_warning; + + +static void +print_warn(void) +{ + if (!no_warning) + { + log_info("WARNING: using insecure memory!\n"); + } +} + + +static void +lock_pool( void *p, size_t n ) +{ +#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK) + int err; + + cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); + err = mlock( p, n ); + if( err && errno ) + err = errno; + cap_set_proc( cap_from_text("cap_ipc_lock+p") ); + + if( err ) { + if( errno != EPERM +#ifdef EAGAIN /* OpenBSD returns this */ + && errno != EAGAIN +#endif +#ifdef ENOSYS /* Some SCOs return this (function not implemented) */ + && errno != ENOSYS +#endif +#ifdef ENOMEM /* Linux can return this */ + && errno != ENOMEM +#endif + ) + log_error("can't lock memory: %s\n", strerror(err)); + show_warning = 1; + } + +#elif defined(HAVE_MLOCK) + uid_t uid; + int err; + + uid = getuid(); + +#ifdef HAVE_BROKEN_MLOCK + /* ick. but at least we get secured memory. about to lock + entire data segment. */ +#ifdef HAVE_PLOCK +# ifdef _AIX + /* The configure for AIX returns broken mlock but the plock has + the strange requirement to somehow set the stack limit first. + The problem might turn out in indeterministic program behaviour + and hanging processes which can somehow be solved when enough + processes are clogging up the memory. To get this problem out + of the way we simply don't try to lock the memory at all. + */ + errno = EPERM; + err = errno; +# else /* !_AIX */ + err = plock( DATLOCK ); + if( err && errno ) + err = errno; +# endif /*_AIX*/ +#else /*!HAVE_PLOCK*/ + if( uid ) { + errno = EPERM; + err = errno; + } + else { + err = mlock( p, n ); + if( err && errno ) + err = errno; + } +#endif /*!HAVE_PLOCK*/ +#else + err = mlock( p, n ); + if( err && errno ) + err = errno; +#endif + + if( uid && !geteuid() ) { + /* check that we really dropped the privs. + * Note: setuid(0) should always fail */ + if( setuid( uid ) || getuid() != geteuid() || !setuid(0) ) + log_fatal("failed to reset uid: %s\n", strerror(errno)); + } + + if( err ) { + if( errno != EPERM +#ifdef EAGAIN /* OpenBSD returns this */ + && errno != EAGAIN +#endif +#ifdef ENOSYS /* Some SCOs return this (function not implemented) */ + && errno != ENOSYS +#endif +#ifdef ENOMEM /* Linux can return this */ + && errno != ENOMEM +#endif + ) + log_error("can't lock memory: %s\n", strerror(err)); + show_warning = 1; + } + +#elif defined ( __QNX__ ) + /* QNX does not page at all, so the whole secure memory stuff does + * not make much sense. However it is still of use because it + * wipes out the memory on a free(). + * Therefore it is sufficient to suppress the warning + */ +#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__) + /* It does not make sense to print such a warning, given the fact that + * this whole Windows !@#$% and their user base are inherently insecure + */ +#else + log_info("Please note that you don't have secure memory on this system\n"); +#endif +} + + +static void +init_pool( size_t n) +{ + long int pgsize_val; + size_t pgsize; + + poolsize = n; + + if( disable_secmem ) + log_bug("secure memory is disabled"); + +#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + pgsize_val = sysconf (_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + pgsize_val = getpagesize (); +#else + pgsize_val = -1; +#endif + pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val : 4096; + + +#ifdef HAVE_MMAP + poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1); +#ifdef MAP_ANONYMOUS + pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#else /* map /dev/zero instead */ + { int fd; + + fd = open("/dev/zero", O_RDWR); + if( fd == -1 ) { + log_error("can't open /dev/zero: %s\n", strerror(errno) ); + pool = (void*)-1; + } + else { + pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, + MAP_PRIVATE, fd, 0); + close (fd); + } + } +#endif + if( pool == (void*)-1 ) + log_info("can't mmap pool of %u bytes: %s - using malloc\n", + (unsigned)poolsize, strerror(errno)); + else { + pool_is_mmapped = 1; + pool_okay = 1; + } + +#endif + if( !pool_okay ) { + pool = malloc( poolsize ); + if( !pool ) + log_fatal("can't allocate memory pool of %u bytes\n", + (unsigned)poolsize); + else + pool_okay = 1; + } + lock_pool( pool, poolsize ); + poollen = 0; +} + + +/* concatenate unused blocks */ +static void +compress_pool(void) +{ + /* fixme: we really should do this */ +} + +void +secmem_set_flags( unsigned flags ) +{ + int was_susp = suspend_warning; + + no_warning = flags & 1; + suspend_warning = flags & 2; + + /* and now issue the warning if it is not longer suspended */ + if( was_susp && !suspend_warning && show_warning ) { + show_warning = 0; + print_warn(); + } +} + +unsigned +secmem_get_flags(void) +{ + unsigned flags; + + flags = no_warning ? 1:0; + flags |= suspend_warning ? 2:0; + return flags; +} + +/* Returns 1 if memory was locked, 0 if not. */ +int +secmem_init( size_t n ) +{ + if( !n ) { +#ifdef USE_CAPABILITIES + /* drop all capabilities */ + cap_set_proc( cap_from_text("all-eip") ); +#elif !defined(HAVE_DOSISH_SYSTEM) + uid_t uid; + disable_secmem=1; + uid = getuid(); + if( uid != geteuid() ) { + if( setuid( uid ) || getuid() != geteuid() || !setuid(0) ) + log_fatal("failed to drop setuid\n" ); + } +#endif + } + else { + if( n < DEFAULT_POOLSIZE ) + n = DEFAULT_POOLSIZE; + if( !pool_okay ) + init_pool(n); + else + log_error("Oops, secure memory pool already initialized\n"); + } + + return !show_warning; +} + + +void * +secmem_malloc( size_t size ) +{ + MEMBLOCK *mb, *mb2; + int compressed=0; + + if( !pool_okay ) { + log_info( + "operation is not possible without initialized secure memory\n"); + log_info("(you may have used the wrong program for this task)\n"); + exit(2); + } + if( show_warning && !suspend_warning ) { + show_warning = 0; + print_warn(); + } + + /* Blocks are always a multiple of 32. Note that we allocate an + extra of the size of an entire MEMBLOCK. This is required + becuase we do not only need the SIZE info but also extra space + to chain up unused memory blocks. */ + size += sizeof(MEMBLOCK); + size = ((size + 31) / 32) * 32; + + retry: + /* try to get it from the used blocks */ + for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next ) + if( mb->size >= size ) { + if( mb2 ) + mb2->u.next = mb->u.next; + else + unused_blocks = mb->u.next; + goto leave; + } + /* allocate a new block */ + if( (poollen + size <= poolsize) ) { + mb = (void*)((char*)pool + poollen); + poollen += size; + mb->size = size; + } + else if( !compressed ) { + compressed=1; + compress_pool(); + goto retry; + } + else + return NULL; + + leave: + cur_alloced += mb->size; + cur_blocks++; + if( cur_alloced > max_alloced ) + max_alloced = cur_alloced; + if( cur_blocks > max_blocks ) + max_blocks = cur_blocks; + + return &mb->u.aligned.c; +} + + +void * +secmexrealloc( void *p, size_t newsize ) +{ + MEMBLOCK *mb; + size_t size; + void *a; + + mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); + size = mb->size; + if (size < sizeof(MEMBLOCK)) + log_bug ("secure memory corrupted at block %p\n", (void *)mb); + size -= ((size_t) &((MEMBLOCK*)0)->u.aligned.c); + + if( newsize <= size ) + return p; /* It is easier not to shrink the memory. */ + a = secmem_malloc( newsize ); + if ( a ) { + memcpy(a, p, size); + memset((char*)a+size, 0, newsize-size); + secmem_free(p); + } + return a; +} + + +void +secmem_free( void *a ) +{ + MEMBLOCK *mb; + size_t size; + + if( !a ) + return; + + mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); + size = mb->size; + /* This does not make much sense: probably this memory is held in the + * cache. We do it anyway: */ + wipememory2(mb, 0xff, size ); + wipememory2(mb, 0xaa, size ); + wipememory2(mb, 0x55, size ); + wipememory2(mb, 0x00, size ); + mb->size = size; + mb->u.next = unused_blocks; + unused_blocks = mb; + cur_blocks--; + cur_alloced -= size; +} + + +/* Check whether P points into the pool. */ +static int +ptr_into_pool_p (const void *p) +{ + /* We need to convert pointers to addresses. This is required by + C-99 6.5.8 to avoid undefined behaviour. Using size_t is at + least only implementation defined. See also + http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html + */ + size_t p_addr = (size_t)p; + size_t pool_addr = (size_t)pool; + + return p_addr >= pool_addr && p_addr < pool_addr+poolsize; +} + + +int +m_is_secure( const void *p ) +{ + return pool_okay && ptr_into_pool_p (p); +} + + + +/**************** + * Warning: This code might be called by an interrupt handler + * and frankly, there should really be such a handler, + * to make sure that the memory is wiped out. + * We hope that the OS wipes out mlocked memory after + * receiving a SIGKILL - it really should do so, otherwise + * there is no chance to get the secure memory cleaned. + */ +void +secmem_term() +{ + if( !pool_okay ) + return; + + wipememory2( pool, 0xff, poolsize); + wipememory2( pool, 0xaa, poolsize); + wipememory2( pool, 0x55, poolsize); + wipememory2( pool, 0x00, poolsize); +#ifdef HAVE_MMAP + if( pool_is_mmapped ) + munmap( pool, poolsize ); +#endif + pool = NULL; + pool_okay = 0; + poolsize=0; + poollen=0; + unused_blocks=NULL; +} + + +void +secmem_dump_stats() +{ + if( disable_secmem ) + return; + fprintf(stderr, + "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n", + cur_alloced, max_alloced, cur_blocks, max_blocks, + (ulong)poollen, (ulong)poolsize ); +} diff -uNr a/smg_comms/mpi/tests/README b/smg_comms/mpi/tests/README --- a/smg_comms/mpi/tests/README false +++ b/smg_comms/mpi/tests/README 0c71b67054a6b49a19c3f8c03751bd4d537843986814b8b970f6a127251e78042bb8da1af5f33d335e69322a7878d33d2a8c50da2956e629eb0a32846258de4e @@ -0,0 +1,8 @@ + S.MG, 2018 + +Building: +gprbuild + +Cleaning: +gprclean + diff -uNr a/smg_comms/mpi/tests/obj/README b/smg_comms/mpi/tests/obj/README --- a/smg_comms/mpi/tests/obj/README false +++ b/smg_comms/mpi/tests/obj/README f829705d787e0de60b165ccd6be182b11c11bc80e43b3b536a2062a7247b102a9ec8906e3d48c0d7ec71d6757678fd573728d12ef3fd3ae2da9924b7593bc581 @@ -0,0 +1 @@ +S.MG, 2018 diff -uNr a/smg_comms/mpi/tests/test_mpi.c b/smg_comms/mpi/tests/test_mpi.c --- a/smg_comms/mpi/tests/test_mpi.c false +++ b/smg_comms/mpi/tests/test_mpi.c 5eb23a86515cc3cb7e47fcdb287828fa70f21a62026ab715be5121f7793abd90f5929fba94f6daa9b3fdb62e159d3319920903dfc7183b2890f492265c96e081 @@ -0,0 +1,145 @@ +#include "mpi.h" +#include "mpi-internal.h" /* for BITS_PER_MPI_LIMB */ +#include + +void err(char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void terpri(FILE *fp) +{ + fprintf(fp, "\n"); +} + +void print_results(MPI in, MPI out, char * title) +{ + fprintf(stdout, "******** %s ********", title); + terpri(stdout); + + fprintf(stdout, "input : "); + mpi_print(stdout, in, 1); + terpri(stdout); + + fprintf(stdout, "output: "); + mpi_print(stdout, out, 1); + terpri(stdout); + + terpri(stdout); + fflush(stdout); +} + +/* + * Test that will fail on original code and will pass after EuCrypt fix is applied. + */ +void test_rshift() +{ + MPI out, in, copy_in; + out = mpi_alloc(0); + in = mpi_alloc(0); + copy_in = mpi_alloc(0); + + mpi_fromstr(out, "0x20E92FE28E1929"); /* some value */ + mpi_fromstr(in, "0x2000000010000001000000002"); + mpi_fromstr(copy_in, "0x2000000010000001000000002"); /* to make sure the actual input is print, since call can modify in */ + + /* print value of BITS_PER_MPI_LIMB */ + fprintf(stdout, "BITS_PER_MPI_LIMB is %d\n", BITS_PER_MPI_LIMB); + + /* shift by 0 */ + mpi_tdiv_q_2exp(out, in, 0); + print_results(copy_in, out, "TEST: right shift by 0"); + + /* shift by multiple of BITS_PER_MPI_LIMB */ + mpi_fromstr(in, "0x2000000010000001000000002"); + + mpi_tdiv_q_2exp(out, in, BITS_PER_MPI_LIMB); + print_results(copy_in, out, "TEST: right shift by BITS_PER_MPI_LIMB"); + + /* shift by non-multiple of BITS_PER_MPI_LIMB */ + mpi_fromstr(in, "0x2000000010000001000000002"); + mpi_tdiv_q_2exp(out, in, BITS_PER_MPI_LIMB - 3); + print_results(copy_in, out, "TEST: right shift by BITS_PER_MPI_LIMB - 3"); + + mpi_free(copy_in); + mpi_free(out); + mpi_free(in); +} + +void test_highbit() +{ + MPI in, set_out, clear_out; + + in = mpi_alloc(0); + set_out = mpi_alloc(0); + clear_out = mpi_alloc(0); + + mpi_fromstr(in, "0x2000000010000002000000004"); + mpi_fromstr(set_out, "0x2000000010000002000000004"); + mpi_fromstr(clear_out, "0x2000000010000002000000004"); + + mpi_set_highbit(set_out, 91); + print_results(in, set_out, "TEST: mpi_set_highbit(in, 91)"); + + mpi_fromstr(set_out, "0x2000000010000002000000004"); + mpi_set_highbit(set_out, 96); + print_results(in, set_out, "TEST: mpi_set_highbit(in, 96)"); + + + mpi_clear_highbit(clear_out, 96); + print_results(in, clear_out, "TEST: mpi_clear_highbit(in, 96)"); + + mpi_fromstr(clear_out, "0x2000000010000002000000004"); + mpi_clear_highbit(clear_out, 1); + print_results(in, clear_out, "TEST: mpi_clear_highbit(in, 1)"); + + mpi_free(in); + mpi_free(set_out); + mpi_free(clear_out); +} + +void test_get_nbits() +{ + MPI m; + int nbits; + + m = mpi_alloc(0); + mpi_fromstr(m, "0x0"); + nbits = mpi_get_nbits(m); + print_results(m, m, "TEST: get_nbits"); + fprintf(stdout, "nbits: %d\n", nbits); + mpi_free(m); +} + +int main(int ac, char **av) +{ + MPI a, b, y; + int r; + + test_rshift(); + test_highbit(); + test_get_nbits(); + + r = secmem_init(1000); + if (r==0) err("secmem init"); + + a = mpi_alloc_secure(0); + b = mpi_alloc_secure(0); + y = mpi_alloc_secure(0); + mpi_fromstr(a, "0x1B0B206C488601"); + mpi_fromstr(b, "0x20E92FE28E1929"); + mpi_mul(y, a, b); + mpi_free(a); + mpi_free(b); + + fprintf(stdout, "******** TEST: mpi_mul, see README ********"); + terpri(stdout); + mpi_print(stdout, y, 1); + mpi_free(y); + + terpri(stdout); + secmem_term(); + + return 0; +} diff -uNr a/smg_comms/mpi/tests/test_mpi.gpr b/smg_comms/mpi/tests/test_mpi.gpr --- a/smg_comms/mpi/tests/test_mpi.gpr false +++ b/smg_comms/mpi/tests/test_mpi.gpr a29b3f2a6d20f115e9150134305105fb5a21567355ece0ddc3e3cfbd3b752d6d6fbfdbb97533f568e75898f04a01cbb555df566b1117b1fee5711a7912e0b29d @@ -0,0 +1,14 @@ +-- S.MG, 2018 + +with "../mpi.gpr"; + +project test_MPI is + for Languages use ("C"); + + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Exec_Dir use "."; + + for Main use ("test_mpi.c"); +end test_MPI; + diff -uNr a/smg_comms/rsa/README b/smg_comms/rsa/README --- a/smg_comms/rsa/README false +++ b/smg_comms/rsa/README c4e10d617469ed871477b2ef41af5dfe7830f97a85b8a5034d2e2c9806202462a566ee6a0412c8a5245cf17fde5e84ca7f6b1ac864adfcb0843e6f4d8f26f571 @@ -0,0 +1,12 @@ +S.MG, 2017 + +This is the S.MG implementation of RSA, used by the Eulora server. + +NB: this lib is part of EuCrypt and as such, it relies on other EuCrypt components (most notably: mpi). + +Compilation: +gprbuild + +Tests: +cd tests +gprbuild diff -uNr a/smg_comms/rsa/bin/README b/smg_comms/rsa/bin/README --- a/smg_comms/rsa/bin/README false +++ b/smg_comms/rsa/bin/README ef968e74fee9d5c5451883afc1a47d0eb8a99c775a6b045040134a7f9c0d80dbec3644ff9d69cf941bdbc718a6d4bed3a27a11d2ef6530453ab6e4955aa45f32 @@ -0,0 +1 @@ +bin folder for smg_rsa lib diff -uNr a/smg_comms/rsa/include/knobs.h b/smg_comms/rsa/include/knobs.h --- a/smg_comms/rsa/include/knobs.h false +++ b/smg_comms/rsa/include/knobs.h feaffacd0ecceec5b42d086f1755fede58dd7244b52b8ef599b7e4ad79b149fcbe55f036a1c46f5bae0a00dd3c50b1dc7d8c1bde9958934cbcd8d01862e29b9d @@ -0,0 +1,19 @@ +#ifndef SMG_RSA_KNOBS_H +#define SMG_RSA_KNOBS_H + +#define ENTROPY_SOURCE "/dev/ttyUSB0" + +/* + * This is the number of witnesses checked by the Miller-Rabin (MR) algorithm for each candidate prime number. + * The value of M_R_ITERATIONS directly affects the outer bound of MR which is calculated as 4^(-M_R_ITERATIONS) + * S.MG's choice of 16 here means an outer bound of 4^(-16) = 0.0000000002, + which is currently considered sufficient for Eulora's needs. + If your needs are different, change this knob accordingly. + * NB: if you use this to make keys for some serious use, an outer bound of 1e-10 is really not nearly good enough + and therefore you'll probably want to *increase* the value of this knob. + */ +#define M_R_ITERATIONS 16 + + +#endif /*SMG_RSA_KNOBS_H*/ + diff -uNr a/smg_comms/rsa/include/smg_rsa.h b/smg_comms/rsa/include/smg_rsa.h --- a/smg_comms/rsa/include/smg_rsa.h false +++ b/smg_comms/rsa/include/smg_rsa.h 73247011fcc9996859cab02ade955cd8d5fa04b85593e182645ebe0f497686abfc771ecdf1e43b0e39506c85b25f365d80a81031fb82f13919e2ff5824eda5ef @@ -0,0 +1,242 @@ +/* smg_rsa.h + * S.MG, 2017 + */ + +#ifndef SMG_RSA_H +#define SMG_RSA_H + +#include "mpi.h" +#include "knobs.h" + +/* A way to determine endianness at runtime. + * Required for diddling a float's mantissa for instance. + */ +static const int onect = 1; +#define is_bigendian() ( (*(char*)&onect) == 0 ) + +/* + * These are constants as per Eulora's protocol specification, NOT knobs! + * Eulora uses RSA keys of 3920 bits (490 octets); + * The above key length means 2 primes of 1960 bits (245 octets) each. + * NB: if you choose here an odd key length in octets you might end up with a smaller actual key, read the code. + */ +static const int KEY_LENGTH_OCTETS = 490; + +typedef struct { + MPI n; /* modulus */ + MPI e; /* public exponent */ +} RSA_public_key; + +typedef struct { + MPI n; /* public modulus */ + MPI e; /* public exponent */ + MPI d; /* private exponent: e*d=1 mod phi */ + MPI p; /* prime p */ + MPI q; /* prime q */ + MPI u; /* inverse of p mod q */ +} RSA_secret_key; + + +/*********truerandom.c*********/ + +/* + * Opens and configures (as per FG requirements) the specified entropy source (e.g. "/dev/ttyUSB0") + * @param source_name the name of the file to open (e.g. "/dev/ttyUSB0") + * @return the descriptor of the open file when successful; negative value otherwise + */ +int open_entropy_source(char* source_name); + + +/* + * Returns noctets random octets (i.e. 8*noctets bits in total) as obtained from EuCrypt's preferred source. + * Preferred source is defined in knobs.h as ENTROPY_SOURCE and should be a TRNG (e.g. Fuckgoats). + * @param nboctets the length of desired random sequence, in octets + * @param out pointer to allocated memory space for the requested random noctets; NB: this method does NOT allocate space! + * @return the actual number of octets that were obtained from the currently configured entropy source (this is equal to noctets on successful read of required noctets) + */ +int get_random_octets(int noctets, unsigned char *out); + +/* Returns noctets random octets as obtained from the specified "from" source; + * NB: the "from" source is considered to be the handle of an already opened stream; + * This method will simply attempt to read from the source as needed! + * + * @param noctets the length of desired random sequence, in octets + * @param out pointer to allocated memory space for the requested random octets; + * NB: this method does NOT allocate space! + * @param from handle of an already opened entropy source - this method will just READ from it as needed + * @return the actual number of octets that were obtained + */ +int get_random_octets_from(int noctets, unsigned char *out, int from); + +/* Returns (in parameter *n) a *potentially biased* random float between 0 and 1 + * Uses bits from ENTROPY_SOURCE but it rounds when converting to float + * NB: This function rounds impredictably. + Use it ONLY if LSB normalization is insignificant to you! + * This function uses rng_uint64 below. + * + * @param n - a float value (LSB rounded) between 0 and 1, obtained using + * a 64-bit random integer (64 bits from ENTROPY_SOURCE) + * @return - a positive value on success and a negative value in case of error + * main possible cause for error: failure to open ENTROPY_SOURCE. + * NB: a non-responsive/malconfigured source can result in blocking + */ +int rng_dirty_float(float *n); + + +/* Returns (in parameter *n) a randomly generated float between 1 and 2 using: + * - the IEEE 754/1985 format for single float representation + * - ENTROPY_SOURCE to obtain bits that are *directly* used as mantissa + * NB: this value is between 1 and 2 due to the normalised format that includes + * an implicit 1 ( i.e. value is (-1)^sign * 2^(e-127) * (1.mantissa) ) + * + * From IEEE 754/1985, a description of the single float format: + * msb means most significant bit + * lsb means least significant bit + * 1 8 23 ... widths + * +-+-------+-----------------------+ + * |s| e | f | + * +-+-------+-----------------------+ + * msb lsb msb lsb ... order + + * A 32-bit single format number X is divided as shown in the figure above. The + * value v of X is inferred from its constituent fields thus: + * 1. If e = 255 and f != 0 , then v is NaN regardless of s + * 2. If e = 255 and f = 0 , then v = (-1)^s INFINITY + * 3. If 0 < e < 255 , then v = (-1)^s * 2^(e-127) * ( 1.f ) + * 4. If e = 0 and f != 0 , then v = (-1)^s * 2^(-126) * ( 0.f ) (denormalized + * numbers) + * 5. If e = 0 and f = 0 , then v = ( -1 )^s * 0 (zero) + * + * @param n - the address of an IEEE 754/1985 float: its mantissa will be set to + * random bits obtained from ENTROPY_SOURCE; its sign will be set + * to 0; its exponent will be set to 127 (the bias value so + * that the actual exponent is 0). + * @return - a positive value on success and a negative value in case of error + * main possible cause for error: failure to open ENTROPY_SOURCE. + * NB: a non-responsive/malconfigured source can result in blocking + */ +int rng_float_754_1985(float *n); + +/* Returns (in parameter *n) a random unsigned integer value on 32 bits. + * Uses random bits from ENTROPY_SOURCE that are directly interpreted as int + * + * @param n - it will contain the random integer obtained by interpreting 32 + * bits from ENTROPY_SOURCE as an unsigned int value on 32 bits. + * @return - a positive value on success and a negative value in case of error + */ +int rng_uint32( uint32_t *n ); + +/* Returns (in parameter *n) a random unsigned integer value on 64 bits. + * Uses random bits from ENTROPY_SOURCE that are directly interpreted as int + * + * @param n - it will contain the random integer obtained by interpreting 64 + * bits from ENTROPY_SOURCE as an unsigned int value on 64 bits. + * @return - a positive value on success and a negative value in case of error + */ +int rng_uint64( uint64_t *n ); + +/*********primegen.c*********/ + +/* + * This is an implementation of the Miller-Rabin probabilistic primality test: + * checking the specified number of randomly-chosen candidate witnesses + * (i.e. with an outer bound of (1/4)^nwitnesses). + * NB: a 1 result from this test means that the given n is indeed composite (non-prime) + but a 0 result does not fully guarantee that n is prime! + If this doesn't make sense to you, read more on probabilistic primality tests. + * @param n the candidate prime number; + the function will investigate whether this number is composite or *likely* to be prime. + How likely? It depends on the number of witnesses checked, see next parameter. + * @param nwitnesses this is the number of randomly chosen candidate witnesses to the compositeness of n + that will be checked; the outer bound of the algorithm depends on this. + * @param entropy_source the source of entropy (ready to read from) that will be used + to choose candidate witnesses to the compositeness of n. + * @return 1 if at least one witness to the compositeness of n has been found + (i.e. n is certainly composite); + 0 if no witness to the compositeness of n was found (i.e. it is likely that n is prime) + * NB: the probability that n is *not* prime although this function returned 0 is + less than (1/4)^nwitnesses, but it is NOT zero. + */ +int is_composite( MPI n, int nwitnesses, int entropy_source); + +/** + * Generates a random number that has passed the Miller-Rabin test for primality (see function is_composite above). + * NB: top 2 bits and bottom bit are ALWAYS 1! (i.e. a mask 110....01 is applied to the random bits) + * a prime of 8*noctets long will have only (8*noctets-3) bits that are randomly chosen! + * NB: this method does NOT allocate space for the requested MPI; it is the caller's responsibility to allocate it! + * The source of randomness is ENTROPY_SOURCE in eucrypt/smg_rsa/include/knobs.h + * The number of witnesses checked by Miller-Rabin is M_R_ITERATIONS in eucrypt/smg_rsa/include/knobs.h + * Preconditions: + * noctets > 0 (at least one octet!) + * output has known allocated memory for at least nlimbs(noctets) + * successful access to the entropy source + * @param noctets the length of the desired prime number, in octets + * @param output an MPI with sufficient memory allocated for a number that is noctets long + */ +void gen_random_prime( unsigned int noctets, MPI output); + +/*********rsa.c*********/ +/* + * Generates a pair of public+private RSA keys using directly the entropy source + * specified in include/knobs.h + * + * ALL RSA keys are 8*KEY_LENGTH_OCTETS bits out of + * 2 8*KEY_LENGTH_OCTETS/2 bits primes, as per TMSR spec. + * + * @param sk a fully-allocated structure to hold the generated keypair (secret +key structure holds all the elements anyway, public key is a subset of this) + * + * NB: this procedure does NOT allocate memory for components in sk! + * caller should ALLOCATE enough memory for all the MPIs in sk + * Precondition: + * MPIs in sk have known allocated memory for the nlimbs fitting their TMSR size + */ +void gen_keypair( RSA_secret_key *sk ); + +/**************** + * Public key operation. Encrypt input with pk and store result into output. + * + * output = input^e mod n , where e,n are elements of pkey. + * NB: caller should allocate *sufficient* memory for output to hold the result. + * NB: NO checks are made on input! + * + * @param output MPI with enough allocated memory to hold result of encryption + * @param input MPI containing content to encrypt; it *has to be* different from +output! + * @param pk the public key that will be used to encrypt input + * + * Precondition: + * output != input + * Output and input have to be two distinct MPIs because of the sorry state of +the underlying mpi lib that can't handle properly the case when those are the +same. + */ +void public_rsa( MPI output, MPI input, RSA_public_key *pk ); + + +/**************** + * Secret key operation. Decrypt input with sk and store result in output. + * + * output = input^d mod n , where d, n are elements of skey. + * + * This implementation uses the Chinese Remainder Theorem (CRT): + * + * out1 = input ^ (d mod (p-1)) mod p + * out2 = input ^ (d mod (q-1)) mod q + * h = u * (out2 - out1) mod q + * output = out1 + h * p + * + * where out1, out2 and h are intermediate values, d,n,p,q,u are elements of +skey. By using CRT, encryption is *faster*. Decide for yourself if this fits +your needs though! + * NB: it is the caller's responsibility to allocate memory for output! + * NB: NO checks are made on input! + * + * @param output MPI with enough allocated memory to hold result of decryption + * @param input MPI containing content to decrypt + * @param sk the secret key that will be used to decrypt input + */ +void secret_rsa( MPI output, MPI input, RSA_secret_key *sk ); + +#endif /*SMG_RSA*/ + diff -uNr a/smg_comms/rsa/obj/README b/smg_comms/rsa/obj/README --- a/smg_comms/rsa/obj/README false +++ b/smg_comms/rsa/obj/README a2eb4b7afc8afe95836f6cf05b0eb589977606525747a45776a1409a65ccd52edb062ef150226ca65e91f66acebec828b050c1a2e946c542eb86d7830323daf3 @@ -0,0 +1 @@ +obj folder for smg_rsa diff -uNr a/smg_comms/rsa/primegen.c b/smg_comms/rsa/primegen.c --- a/smg_comms/rsa/primegen.c false +++ b/smg_comms/rsa/primegen.c 992c1ed9b3037031c841db0bb5d6467d2142acce1e9b67ddf91d1661d7a9731452d2f2d95222aac51ee7672a781fd2bb195692d3949e14eaf46b8e29d2243fe0 @@ -0,0 +1,152 @@ +/* primegen.c - prime number generation and checks + * + * S.MG, 2017 + * + */ + +#include +#include +#include + +#include "smg_rsa.h" + +/**************** + * is_composite + * Returns 1 if it finds evidence that n is composite and 0 otherwise. + * NB: this is a probabilistic test and its strength is directly linked to: + * - the number of witnesses AND + * - the quality of the entropy source given as arguments! + */ + +int is_composite( MPI n, int nwitnesses, int entropy_source) { + int evidence = 0; + int nlimbs = mpi_get_nlimbs(n); /* see MPI representation */ + unsigned int nbits = mpi_get_nbits(n); /* used bits */ + unsigned int noctets = (nbits + 7) / 8; /* source works on octets */ + + MPI nminus1 = mpi_alloc(nlimbs); /* n-1 value is used a LOT */ + MPI mpi2 = mpi_alloc_set_ui(2); /* 2 as MPI */ + MPI a = mpi_alloc(nlimbs); /* candidate witness */ + MPI y = mpi_alloc(nlimbs); /* intermediate values */ + MPI r = mpi_alloc(nlimbs); /* n = 1 + 2^s * r */ + int s; /* n = 1 + 2^s * r */ + int j; /* counter for loops */ + int nread; /* number of random octets actually read */ + + /* precondition: n > 3 */ + assert( nbits > 2 ); + + /* nminus1 = n - 1 as MPI */ + mpi_sub_ui( nminus1, n, 1); + + /* + * find r odd and s so that n = 1 + 2^s * r + * n-1 = 2^s * r + * s is given by the number of trailing zeros of binary n-1 + * r is then obtained as (n-1) / (2^s) + */ + s = mpi_trailing_zeros( nminus1 ); + mpi_tdiv_q_2exp(r, nminus1, s); + + /* + * Investigate randomly chosen candidate witnesses. + * Stop when either: + * the specified number of witnesses (nwitnesses) have + been investigated OR + * a witness for compositeness of n was found + */ + while (nwitnesses > 0 && evidence == 0) { + unsigned char *p = xmalloc(noctets); + do { + nread = get_random_octets_from(noctets, p, entropy_source); + } while (nread != noctets); + + mpi_set_buffer(a, p, noctets, 0); + + /* ensure that a < n-1 by making a maximum nbits-1 long: + * clear all bits above nbits-2 in a + * keep value of bit nbits-2 in a as it was + */ + if (mpi_test_bit(a, nbits - 2)) + mpi_set_highbit(a, nbits - 2); + else + mpi_clear_highbit(a, nbits - 2); + + /* ensure that 1 < a < n-1; if not, try another random number + * NB: true random means a CAN end up as 0 or 1 here. + */ + if (mpi_cmp(a, nminus1) < 0 && mpi_cmp_ui(a, 1) > 0) { + /* calculate y = a^r mod n */ + mpi_powm(y, a, r, n); + if (mpi_cmp_ui(y, 1) && mpi_cmp(y, nminus1)) { + j = 1; + while ( (j < s) && mpi_cmp(y, nminus1) && (evidence == 0) ) { + /* calculate y = y^2 mod n */ + mpi_powm(y, y, mpi2, n); + if (mpi_cmp_ui(y, 1) == 0) + evidence = 1; + j = j + 1; + } /* end while */ + if (mpi_cmp(y, nminus1)) + evidence = 1; + } /* end if y != 1 and y != n-1 */ + nwitnesses = nwitnesses - 1; + } /* end if 1 < a < n-1 */ + xfree(p); + } /* end while for investigating candidate witnesses */ + + mpi_free( nminus1 ); + mpi_free( mpi2 ); + mpi_free( a ); + mpi_free( y ); + mpi_free( r ); + + return evidence; +} + +/** + * Generates a random number that has passed the Miller-Rabin test for primality (see function is_composite above). + * NB: top 2 bits and bottom bit are ALWAYS 1! (i.e. a mask 11.....1 is applied) + * a prime of 8*noctets long will have only 8*noctets-3 bits that are randomly chosen + * NB: this method does NOT allocate space for the requested MPI; it is the caller's responsibility to allocate it! + * The source of randomness is ENTROPY_SOURCE in eucrypt/smg_rsa/include/knobs.h + * The number of witnesses checked by Miller-Rabin is M_R_ITERATIONS in eucrypt/smg_rsa/include/knobs.h + * Preconditions: + * noctets > 0 (at least one octet!) + * memory allocated for noctets in output MPI + * successful access to the entropy source + */ +void gen_random_prime( unsigned int noctets, MPI output ) +{ + /* precondition: at least one octet long */ + assert(noctets > 0); + + /* precondition: enough memory allocated for the limbs corresponding to noctets */ + unsigned int nlimbs = mpi_nlimb_hint_from_nbytes(noctets); + assert(mpi_get_alloced(output) >= nlimbs); + + /* precondition: access to the entropy source */ + int entropy_source = open_entropy_source(ENTROPY_SOURCE); /* source of random bits */ + assert(entropy_source >= 0); + + unsigned int nbits = 8*noctets; /* length of MPI in bits */ + + /* + * loop until a prime is found: get noctets of random bits, trim and apply 110...01 mask, check if prime + */ + unsigned char *p = xmalloc( noctets ); + int nread; + do { + do { + nread = get_random_octets_from( noctets, p, entropy_source ); + } while ( nread != noctets ); + mpi_set_buffer( output, p, noctets, 0); /* convert to MPI representation */ + mpi_set_highbit( output, nbits - 1 ); /* trim at required size and set top bit */ + mpi_set_bit( output, nbits - 2); /* set second top bit */ + mpi_set_bit( output, 0 ); /* set bottom bit to unsure odd number */ + } while (is_composite(output, M_R_ITERATIONS, entropy_source)); + + /* tidy up, a prime was found */ + xfree(p); + close(entropy_source); +} diff -uNr a/smg_comms/rsa/rsa.c b/smg_comms/rsa/rsa.c --- a/smg_comms/rsa/rsa.c false +++ b/smg_comms/rsa/rsa.c 388a33be262faa152fb74089b6ac814c7e5c6248a5b52f91a8c69c0e19ec9f9eea12b0551b0aadc751f73cdd5ac4004c8c493aa1e6041118a922070ead3a7ecb @@ -0,0 +1,140 @@ +/* + * An implementation of TMSR RSA + * S.MG, 2018 + */ + +#include "smg_rsa.h" +#include + +void gen_keypair( RSA_secret_key *sk ) { + /* precondition: sk is not null */ + assert(sk != NULL); + + /* precondition: enough memory allocated, corresponding to key size */ + int noctets_pq = KEY_LENGTH_OCTETS / 2; + unsigned int nlimbs_pq = mpi_nlimb_hint_from_nbytes( noctets_pq); + unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS); + assert( mpi_get_alloced( sk->n) >= nlimbs_n); + assert( mpi_get_alloced( sk->p) >= nlimbs_pq); + assert( mpi_get_alloced( sk->q) >= nlimbs_pq); + + /* helper variables for calculating Euler's totient phi=(p-1)*(q-1) */ + MPI p_minus1 = mpi_alloc(nlimbs_pq); + MPI q_minus1 = mpi_alloc(nlimbs_pq); + MPI phi = mpi_alloc(nlimbs_n); + + /* generate 2 random primes, p and q*/ + /* gen_random_prime sets top 2 bits to 1 so p*q will have KEY_LENGTH bits */ + /* in the extremely unlikely case that p = q, discard and generate again */ + do { + gen_random_prime( noctets_pq, sk->p); + gen_random_prime( noctets_pq, sk->q); + } while ( mpi_cmp( sk->p, sk->q) == 0); + + /* swap if needed, to ensure p < q for calculating u */ + if ( mpi_cmp( sk->p, sk->q) > 0) + mpi_swap( sk->p, sk->q); + + /* calculate helper for Chinese Remainder Theorem: + u = p ^ -1 ( mod q ) + this is used to speed-up decryption. + */ + mpi_invm( sk->u, sk->p, sk->q); + + /* calculate modulus n = p * q */ + mpi_mul( sk->n, sk->p, sk->q); + + /* calculate Euler totient: phi = (p-1)*(q-1) */ + mpi_sub_ui( p_minus1, sk->p, 1); + mpi_sub_ui( q_minus1, sk->q, 1); + mpi_mul( phi, p_minus1, q_minus1); + + /* choose random prime e, public exponent, with 3 < e < phi */ + /* because e is prime, gcd(e, phi) is always 1 so no need to check it */ + do { + gen_random_prime( noctets_pq, sk->e); + } while ( (mpi_cmp_ui(sk->e, 3) < 0) || (mpi_cmp(sk->e, phi) > 0)); + + /* calculate private exponent d, 1 < d < phi, where e * d = 1 mod phi */ + mpi_invm( sk->d, sk->e, phi); + + /* tidy up: free locally allocated memory for helper variables */ + mpi_free(phi); + mpi_free(p_minus1); + mpi_free(q_minus1); +} + +void public_rsa( MPI output, MPI input, RSA_public_key *pk ) { + + /* mpi_powm can't handle output and input being same */ + assert (output != input); + + /* the actual rsa op */ + mpi_powm( output, input, pk->e, pk->n ); + +} + +void secret_rsa( MPI output, MPI input, RSA_secret_key *skey ) { + /* at its simplest, this would be input ^ d (mod n), hence: + * mpi_powm( output, input, skey->d, skey->n ); + * for faster decryption though, we'll use CRT and Garner's algorithm, hence: + * u = p ^ (-1) (mod q) , already calculated and stored in skey + * dp = d mod (p-1) + * dq = d mod (q-1) + * m1 = input ^ dp (mod p) + * m2 = input ^ dq (mod q) + * h = u * (m2 - m1) mod q + * output = m1 + h * p + * Note that same CRT speed up isn't available for encryption because at +encryption time not enough information is available (only e and n are known). + */ + + /* allocate memory for all local, helper MPIs */ + MPI p_minus1 = mpi_alloc( mpi_get_nlimbs( skey->p) ); + MPI q_minus1 = mpi_alloc( mpi_get_nlimbs( skey->q) ); + int nlimbs = mpi_get_nlimbs( skey->n ) + 1; + MPI dp = mpi_alloc( nlimbs ); + MPI dq = mpi_alloc( nlimbs ); + MPI m1 = mpi_alloc( nlimbs ); + MPI m2 = mpi_alloc( nlimbs ); + MPI h = mpi_alloc( nlimbs ); + + /* p_minus1 = p - 1 */ + mpi_sub_ui( p_minus1, skey->p, 1 ); + + /* dp = d mod (p - 1) aka remainder of d / (p - 1) */ + mpi_fdiv_r( dp, skey->d, p_minus1 ); + + /* m1 = input ^ dp (mod p) */ + mpi_powm( m1, input, dp, skey->p ); + + /* q_minus1 = q - 1 */ + mpi_sub_ui( q_minus1, skey->q, 1 ); + + /* dq = d mod (q - 1) aka remainder of d / (q - 1) */ + mpi_fdiv_r( dq, skey->d, q_minus1 ); + + /* m2 = input ^ dq (mod q) */ + mpi_powm( m2, input, dq, skey->q ); + + /* h = u * ( m2 - m1 ) mod q */ + mpi_sub( h, m2, m1 ); + if ( mpi_is_neg( h ) ) + mpi_add ( h, h, skey->q ); + mpi_mulm( h, skey->u, h, skey->q ); + + /* output = m1 + h * p */ + mpi_mul ( h, h, skey->p ); + mpi_add ( output, m1, h ); + + /* tidy up */ + mpi_free ( p_minus1 ); + mpi_free ( q_minus1 ); + mpi_free ( dp ); + mpi_free ( dq ); + mpi_free ( m1 ); + mpi_free ( m2 ); + mpi_free ( h ); + +} + diff -uNr a/smg_comms/rsa/rsa.gpr b/smg_comms/rsa/rsa.gpr --- a/smg_comms/rsa/rsa.gpr false +++ b/smg_comms/rsa/rsa.gpr 88b2abcf9faf9d0689673cc368d3e3c853147de327eec636b90cba1a085eb1e8b14ae9eee8521f121b9f5eecbecd5078a2efe52df1fd5a1d097e605a27a244d2 @@ -0,0 +1,15 @@ + -- S.MG, 2018 + +with "../mpi/mpi.gpr"; + +project RSA is + for Languages use ("C"); + for Library_Name use "RSA"; + for Library_Kind use "static"; + + for Source_Dirs use (".", "include"); + for Object_Dir use "obj"; + for Library_Dir use "bin"; + +end RSA; + diff -uNr a/smg_comms/rsa/tests/obj/README b/smg_comms/rsa/tests/obj/README --- a/smg_comms/rsa/tests/obj/README false +++ b/smg_comms/rsa/tests/obj/README a2eb4b7afc8afe95836f6cf05b0eb589977606525747a45776a1409a65ccd52edb062ef150226ca65e91f66acebec828b050c1a2e946c542eb86d7830323daf3 @@ -0,0 +1 @@ +obj folder for smg_rsa diff -uNr a/smg_comms/rsa/tests/smg_rsa_tests.gpr b/smg_comms/rsa/tests/smg_rsa_tests.gpr --- a/smg_comms/rsa/tests/smg_rsa_tests.gpr false +++ b/smg_comms/rsa/tests/smg_rsa_tests.gpr 658150d9cc3ff5f1d4a6d134c57d9ea6740be6aef571ef9c2bd553a3e4931a541ccf755bf51dc5349a4dbaecf04dc11e0d4faff4d4745e322cf22231241570f5 @@ -0,0 +1,13 @@ + -- Tests for SMG_RSA (part of EuCrypt) + -- S.MG, 2018 + +with "../smg_rsa.gpr"; + +project SMG_RSA_Tests is + for Languages use("C"); + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Exec_Dir use "."; + + for Main use ("tests.c"); +end SMG_RSA_Tests; diff -uNr a/smg_comms/rsa/tests/tests.c b/smg_comms/rsa/tests/tests.c --- a/smg_comms/rsa/tests/tests.c false +++ b/smg_comms/rsa/tests/tests.c 89b1c405d92e249341bdc0bddc5a98d8ae8dd0349e04a165063d938f01df557a057be544c51b0efb6d72d505f1424a1aa3a6d7957e83f229711677240123e2fd @@ -0,0 +1,761 @@ +#include "smg_rsa.h" +#include "mpi.h" + +#include +#include +#include +#include + +extern void adainit(void); +extern void adafinal(void); + +void err(char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void time_entropy_source(int nruns, int noctets) { + unsigned char buffer[noctets]; + int read, i; + struct timespec tstart, tend; + long int diff; + + clock_gettime(CLOCK_MONOTONIC, &tstart); + for (i=0; i buffer_length) + to_read = buffer_length; + + nread = get_random_octets_from(to_read, buffer, source); + if (nread > 0) { + total_read = total_read + nread; + fwrite(buffer, 1, nread, out); + fflush(out); + printf("."); + fflush(stdout); + } + } + printf("done.\n"); + + fclose(out); + close(source); +} + +void test_is_composite(int nruns, char *hex_number, int expected) { + int i; + int output; + int count_ok = 0; + int source = open_entropy_source(ENTROPY_SOURCE); + MPI p = mpi_alloc(0); + + mpi_fromstr(p, hex_number); + printf("TEST is_composite on MPI(hex) "); + mpi_print(stdout, p, 1); + for (i=0; i < nruns; i++) { + printf("."); + fflush(stdout); + output = is_composite(p, M_R_ITERATIONS, source); + if (output == expected) + count_ok = count_ok + 1; + } + printf("done, with %d out of %d correct runs for expected=%d: %s\n", count_ok, nruns, expected, count_ok==nruns? "PASS":"FAIL"); + mpi_free(p); + close(source); +} + +void time_mr(int nruns) { + struct timespec tstart, tend; + long int diff; + int i; + MPI prime; + unsigned int noctets = KEY_LENGTH_OCTETS / 2; + unsigned int nlimbs = mpi_nlimb_hint_from_nbytes(noctets); + + int entropy_source = open_entropy_source(ENTROPY_SOURCE); + if (entropy_source <= 0) + err("can't open entropy source!"); + + /* first generate a prime of half key length, to make sure M-R will run max number of iterations */ + printf("Generating a prime number of %d octets length for M-R timing test\n", noctets); + prime = mpi_alloc(nlimbs); + gen_random_prime(noctets, prime); + + printf("Running timing test for Miller-Rabin with %d repetitions and %d witnesses on prime number ", nruns, M_R_ITERATIONS); + mpi_print(stdout, prime, 1); + printf("\n"); + /* now do the actual runs and time it all */ + clock_gettime(CLOCK_MONOTONIC, &tstart); + for (i=0; in); + pk.e = mpi_copy(sk->e); + unsigned char *p; + p = xmalloc(noctets); + + fprintf(file, "TEST encrypt/decrypt on %d octets of random data\n", noctets); + fflush(file); + if (get_random_octets( noctets, p) == noctets) { + mpi_set_buffer( test, p, noctets, 0 ); + + fprintf(file, "TEST data:\n"); + mpi_print(file, test, 1); + fprintf(file, "\n"); + fflush(file); + + public_rsa( out1, test, &pk ); + secret_rsa( out2, out1, sk ); + + fprintf(file, "ENCRYPTED with PUBLIC key data:\n"); + mpi_print(file, out1, 1); + fprintf(file, "\n"); + fflush(file); + + fprintf(file, "DECRYPTED with SECRET key:\n"); + mpi_print(file, out2, 1); + fprintf(file, "\n"); + fflush(file); + + if( mpi_cmp( test, out2 ) ) + fprintf(file, "FAILED: RSA operation: public(secret) failed\n"); + else + fprintf(file, "PASSED: RSA operation: public(secret) passed\n"); + fflush(file); + + secret_rsa( out1, test, sk ); + public_rsa( out2, out1, &pk ); + if( mpi_cmp( test, out2 ) ) + fprintf(file, "FAILED: RSA operation: secret(public) failed\n"); + else + fprintf(file, "PASSED: RSA operation: secret(public) passed\n"); + } + else + fprintf(file, "FAILED: not enough bits returned from entropy source\n"); + + fflush(file); + xfree(p); + mpi_free( pk.n); + mpi_free( pk.e); + + mpi_free( test ); + mpi_free( out1 ); + mpi_free( out2 ); +} + +void test_rsa( int nruns, FILE *fkeys, FILE *fout) { + RSA_secret_key sk; + int noctets = KEY_LENGTH_OCTETS; + int noctets_pq = noctets / 2; + int nlimbs = mpi_nlimb_hint_from_nbytes(noctets); + int nlimbs_pq = mpi_nlimb_hint_from_nbytes(noctets_pq); + int i; + + sk.n = mpi_alloc(nlimbs); + sk.e = mpi_alloc(nlimbs); + sk.d = mpi_alloc(nlimbs); + sk.p = mpi_alloc(nlimbs_pq); + sk.q = mpi_alloc(nlimbs_pq); + sk.u = mpi_alloc(nlimbs_pq); + + printf("TEST RSA key generation and use with %d runs\n", nruns); + fflush(stdout); + + for (i = 0;i < nruns; i++) { + gen_keypair(&sk); + printf("."); + fflush(stdout); + + mpi_print(fkeys, sk.n, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + mpi_print(fkeys, sk.e, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + mpi_print(fkeys, sk.d, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + mpi_print(fkeys, sk.p, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + mpi_print(fkeys, sk.q, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + mpi_print(fkeys, sk.u, 1); + fwrite("\n", sizeof(char), 1, fkeys); + + test_rsa_keys(&sk, noctets_pq, fout); + printf("*"); + fflush(stdout); + } + + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); + +} + +void test_rsa_exp() { + MPI msg = mpi_alloc(0); + MPI expected = mpi_alloc(0); + MPI result; + + RSA_public_key pk; + pk.n = mpi_alloc(0); + pk.e = mpi_alloc(0); + + printf("TEST verify of rsa exponentiation on input data: \n"); + + mpi_fromstr(msg, "0x\ +5B6A8A0ACF4F4DB3F82EAC2D20255E4DF3E4B7C799603210766F26EF87C8980E737579\ +EC08E6505A51D19654C26D806BAF1B62F9C032E0B13D02AF99F7313BFCFD68DA46836E\ +CA529D7360948550F982C6476C054A97FD01635AB44BFBDBE2A90BE06F7984AC8534C3\ +8613747F340C18176E6D5F0C10246A2FCE3A668EACB6165C2052497CA2EE483F4FD8D0\ +6A9911BD97E9B6720521D872BD08FF8DA11A1B8DB147F252E4E69AE6201D3B374B171D\ +F445EF2BF509D468FD57CEB5840349B14C6E2AAA194D9531D238B85B8F0DD352D1E596\ +71539B429849E5D965E438BF9EFFC338DF9AADF304C4130D5A05E006ED855F37A06242\ +28097EF92F6E78CAE0CB97"); + + mpi_fromstr(expected, "0x\ +1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003051300\ +D0609608648016503040203050004406255509399A3AF322C486C770C5F7F6E05E18FC\ +3E2219A03CA56C7501426A597187468B2F71B4A198C807171B73D0E7DBC3EEF6EA6AFF\ +693DE58E18FF84395BE"); + result = mpi_alloc( mpi_get_nlimbs(expected) ); + + mpi_fromstr(pk.n, "0x\ +CDD49A674BAF76D3B73E25BC6DF66EF3ABEDDCA461D3CCB6416793E3437C7806562694\ +73C2212D5FD5EED17AA067FEC001D8E76EC901EDEDF960304F891BD3CAD7F9A335D1A2\ +EC37EABEFF3FBE6D3C726DC68E599EBFE5456EF19813398CD7D548D746A30AA47D4293\ +968BFBAFCBF65A90DFFC87816FEE2A01E1DC699F4DDABB84965514C0D909D54FDA7062\ +A2037B50B771C153D5429BA4BA335EAB840F9551E9CD9DF8BB4A6DC3ED1318FF3969F7\ +B99D9FB90CAB968813F8AD4F9A069C9639A74D70A659C69C29692567CE863B88E191CC\ +9535B91B417D0AF14BE09C78B53AF9C5F494BCF2C60349FFA93C81E817AC682F0055A6\ +07BB56D6A281C1A04CEFE1"); + + mpi_fromstr( pk.e, "0x10001"); + + mpi_print( stdout, msg, 1); + printf("\n"); + + public_rsa( result, msg, &pk); + if ( mpi_cmp( result, expected) != 0 ) + printf( "FAILED\n"); + else + printf( "PASSED\n"); + + printf("Expected:\n"); + mpi_print( stdout, expected, 1); + printf("\n"); + + printf("Obtained:\n"); + mpi_print( stdout, result, 1); + printf("\n"); + + mpi_free( pk.n ); + mpi_free( pk.e ); + mpi_free( msg ); + mpi_free( expected ); + mpi_free( result ); +} + +void time_rsa_gen( int nruns ) { + struct timespec tstart, tend; + long int diff; + int i; + + RSA_secret_key sk; + int noctets = KEY_LENGTH_OCTETS; + int noctets_pq = noctets / 2; + int nlimbs = mpi_nlimb_hint_from_nbytes(noctets); + int nlimbs_pq = mpi_nlimb_hint_from_nbytes(noctets_pq); + sk.n = mpi_alloc(nlimbs); + sk.e = mpi_alloc(nlimbs); + sk.d = mpi_alloc(nlimbs); + sk.p = mpi_alloc(nlimbs_pq); + sk.q = mpi_alloc(nlimbs_pq); + sk.u = mpi_alloc(nlimbs_pq); + + clock_gettime(CLOCK_MONOTONIC, &tstart); + for (i = 0;i < nruns; i++) { + gen_keypair(&sk); + } + clock_gettime(CLOCK_MONOTONIC, &tend); + + diff = tend.tv_sec-tstart.tv_sec; + + printf("TOTAL: %ld seconds for generating %d key pairs\n", diff, nruns); + printf("Average (%d runs): %f seconds per TMSR RSA key pair.\n", + nruns, diff / (1.0*nruns)); + mpi_free(sk.n); + mpi_free(sk.e); + mpi_free(sk.d); + mpi_free(sk.p); + mpi_free(sk.q); + mpi_free(sk.u); +} + +void test_oaep_encr_decr( int nruns ) { + /* a set of RSA keys previously generated with eucrypt */ + RSA_public_key pk; + pk.n = mpi_alloc(0); + pk.e = mpi_alloc(0); + + RSA_secret_key sk; + sk.n = mpi_alloc(0); + sk.e = mpi_alloc(0); + sk.d = mpi_alloc(0); + sk.p = mpi_alloc(0); + sk.q = mpi_alloc(0); + sk.u = mpi_alloc(0); + + mpi_fromstr(sk.n, "0x\ +CD2C025323BEA46FFF2FA8D7A9D39817EA713421F4AE03FA8120641193892A70BFECF5\ +83101635A432110D3DDE6339E3CC7ECC0AD91C026FCACE832DD3888A6FCA7BCE56C390\ +5A5AC8C7BC921DA675E4B62489B254EB34659D547D71165BC998983A81937BD251AEE1\ +2D985EC387D5376F5DCC5EF7EC530FBD6FD2AA7285EE1AF3335EA73163F0954F30402E\ +D7B374EE84A97B1849B0674B0DA0A2050BD79B71ABB1559F3A9CFDB8557DED7BC90CF2\ +09E8A847E9C226140845B7D03842162E7DA5DD16326CB1F71A248D841FE9076A09911F\ +2F4F5E3EA44EA8DE40332BF00406990BCCF61C322A03C456EF3A98B341E0BDBC1088CE\ +683E78510E76B72C2BCC1EE9AEDD80FFF18ABFC5923B2F36B581C25114AB2DF9F6C2B1\ +9481703FD19E313DCD7ACE15FA11B27D25BCE5388C180A7E21167FB87750599E1ED7C7\ +50F4A844E1DC2270C62D19671CF8F4C25B81E366B09FC850AE642136D204A9160AEECE\ +575B57378AA439E9DD46DC990288CD54BAA35EEE1C02456CD39458A6F1CBF012DCEDF4\ +27CCF3F3F53645658FC49C9C9D7F2856DB571D92B967AB5845514E0054DDB49099F5DD\ +04A6F6F5C5CE642276834B932881AEB648D1F25E9223971F56E249EF40CF7D80F22621\ +CDD0260E9E7D23746960ADB52CF2987584FB1DE95A69A39E5CB12B76E0F5C1A0529C0C\ +065D2E35720810F7C7983180B9A9EA0E00C11B79DC3D"); + + mpi_fromstr(sk.e, "0x\ +DD4856B4EE3D099A8604AE392D8EFEC094CDF01546A28BE87CB484F999E8E75CDFCD01\ +D04D455A6A9254C60BD28C0B03611FC3E751CC27EF768C0B401C4FD2B27C092834A6F2\ +49A145C4EDC47A3B3D363EC352462C945334D160AF9AA72202862912493AC6190AA3A6\ +149D4D8B9996BA7927D3D0D2AD00D30FD630CF464E6CAF9CF49355B9A70E05DB7AE915\ +F9F602772F8D11E5FCDFC7709210F248052615967090CC1F43D410C83724AA5912B2F0\ +52E6B39449A89A97C79C92DC8CB8DEEFCF248C1E1D2FC5BFE85165ECA31839CAA9CEB3\ +3A92EBDC0EB3BAC0F810938BB173C7DA21DCBB2220D44CBA0FD40A2C868FC93AC5243E\ +C137C27B0A76D65634EBB3"); + + mpi_fromstr(sk.d, "0x\ +7C8A6FA1199D99DCA45E9BDF567CA49D02B237340D7E999150BC4883AE29DEC5158521\ +B338F35DC883792356BDDBB3C8B3030A6DD4C6522599A3254E751F9BA1CB1061C5633C\ +81BBFACF6FCD64502614102DFED3F3FA284066C342D5E00953B415915331E30812E5FB\ +CD6680ADCCDEE40B8376A3A225F2E160EA59C7566804526D73BB660A648A3EF9802313\ +B2F841E8458B2AAACE7AACF31083E8F3F630298138393BC88BBD7D4AA4334949651D25\ +365B10DBF4A4A08E20A6CC74BFDD37C1C38E2ADC2A283DF06590DF06B46F67F6ACA67F\ +AC464C795261659A2F9558802D0BBAA05FD1E1AF2CDC70654723DF7EFAEA148B8CDBEB\ +C89EA2320AB9BBB1BC4311475DF3D91446F02EF192368DFEBAC598CCFD4407DEC58FDC\ +1A94CCDD6E5FBA9C52164ACEA8AEE633E557BCCEACB7A1AF656C379482D784A120A725\ +32F9B2B35173D505F21D5AD4CB9511BC836DC923730B70291B70290A216CA3B21CFF79\ +E895C35F4F7AF80E1BD9ED2773BD26919A76E4298D169160593E0335BE2A2A2D2E8516\ +948F657E1B1260E18808A9D463C108535FB60B3B28F711C81E5DE24F40214134A53CE5\ +9A952C8970A1D771EBEFFA2F4359DCF157995B3F1950DE3C6EC41B7FF837148F55F323\ +372AF3F20CE8B8038E750C23D8F5041FA951327859B0E47483F0A47103EF808C72C251\ +006FA526245291C8C84C12D2EF63FB2301EA3EEDA42B"); + + mpi_fromstr(sk.p, "0x\ +E236732452039C14EC1D3B8095BDDCFB7625CE27B1EA5394CF4ED09D3CEECAA4FC0BF6\ +2F7CE975E0C8929CE84B0259D773EA038396479BF15DA065BA70E549B248D77B4B23ED\ +A267308510DBEE2FD44E35D880EE7CFB81E0646AA8630165BD8988C3A8776D9E704C20\ +AA25CA0A3C32F27F592D5FD363B04DD57D8C61FFDCDFCCC59E2913DE0EE47769180340\ +E1EA5A803AA2301A010FF553A380F002601F0853FCACDB82D76FE2FACBCD6E5F294439\ +0799EA5AE9D7880D4E1D4AE146DC1D4E8495B9DD30E57E883923C5FC26682B7142D35C\ +D8A0FC561FE725A6CF419B15341F40FE0C31132CBD81DD8E50697BD1EBFFA16B522E16\ +F5B49A03B707218C7DA60B"); + + mpi_fromstr(sk.q, "0x\ +E830482A3C4F5C3A7E59C10FF8BA760DB1C6D55880B796FFDA4A82E0B60E974E81D04B\ +2A4AD417823EBFB4E8EFB13782943562B19B6C4A680E3BA0C8E37B5023470F4F1AC1F8\ +A0B10672EF75CD58BCD45E6B14503B8A6A70AFE79F6201AF56E7364A1C742BE1453FD2\ +24FDC9D66522EAF4466A084BCB9E46D455A2946E94CBF028770F38D0B741C2CC59308F\ +71D8C2B4B9C928E0AE8D68DEB48A3E9EFD84A10301EBD55F8221CA32FC567B306B2A8E\ +116350AFB995859FDF4378C5CFD06901494E8CFA5D8FAC564D6531FA8A2E4761F5EFBA\ +F78750B6F4662BE9EA4C2FAD67AF73EEB36B41FC15CB678810C19A51DF23555695C4C1\ +546F3FACA39CAA7BB8DBD7"); + + mpi_fromstr(sk.u, "0x\ +846232322775C1CD7D5569DC59E2F3E61A885AE2E9C4A4F8CB3ACBE8C3A5441E5FE348\ +A2A8AC9C2998FBF282222BF508AA1ECF66A76AEDD2D9C97028BFD3F6CA0542E38A5312\ +603C70B95650CE73F80FDD729988FBDB5595A5BF8A007EA34E54994A697906CE56354C\ +E00DF10EB711DEC274A62494E3D350D88736CF67A477FB600AC9F1D6580727585092BF\ +5EBC092CC4D6CF75769051033A1197103BE269942F372168A53771746FBA18ED6972D5\ +0B935A9B1D6B5B3DD50CD89A27FE93C10924E9103FACF7B4C5724A046C3D3B50CC1C78\ +5F5C8E00DBE1D6561F120F5294C170914BC10F978ED4356EED67A9F3A60D70AFE540FC\ +5373CBAE3D0A7FD1C87273"); + + /* copy the public key components */ + pk.n = mpi_copy( sk.n ); + pk.e = mpi_copy( sk.e ); + + /* some plain text message */ + MPI msg = mpi_alloc(0); + mpi_fromstr(msg, "0x\ +5B6A8A0ACF4F4DB3F82EAC2D20255E4DF3E4B7C799603210766F26EF87C8980E737579\ +EC08E6505A51D19654C26D806BAF1B62F9C032E0B13D02AF99F7313BFCFD68DA46836E\ +CA529D7360948550F982C6476C054A97FD01635AB44BFBDBE2A90BE06F7984AC8534C3\ +28097EF92F6E78CAE0CB97"); + + /* actual testing */ + printf("TEST verify oaep_encr_decr on message: \n"); + mpi_print( stdout, msg, 1); + printf("\n"); + + int nlimbs_n = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS); + MPI encr = mpi_alloc( nlimbs_n ); + MPI decr = mpi_alloc( nlimbs_n ); + int success; + + adainit(); + rsa_oaep_encrypt( encr, msg, &pk ); + rsa_oaep_decrypt( decr, encr, &sk, &success ); + + if (success <= 0 || + mpi_cmp(encr, msg) == 0 || + mpi_cmp(msg, decr) != 0) + printf("FAILED: success flag is %d\n", success); + else + printf("PASSED\n"); + + /* attempt to decrypt corrupted block */ + mpi_clear( decr ); + rsa_oaep_decrypt( decr, pk.n, &sk, &success); + if (success > 0) + printf("FAILED: attempt to decrypt non-/corrupted oaep block\n"); + else + printf("PASSED: attempt to decrypt non-/corrupted oaep block\n"); + adafinal(); + + /* clean up */ + mpi_free( sk.n ); + mpi_free( sk.e ); + mpi_free( sk.d ); + mpi_free( sk.p ); + mpi_free( sk.q ); + mpi_free( sk.u ); + + mpi_free( pk.n ); + mpi_free( pk.e ); + + mpi_free( msg ); + mpi_free( encr ); + mpi_free( decr ); +} + +void test_mpi_buffer() { + unsigned int noctets = 10; + int nlimbs = mpi_nlimb_hint_from_nbytes( noctets ); + MPI m = mpi_alloc( nlimbs ); + unsigned char *setbuffer = xmalloc( noctets ); + unsigned char *getbuffer; + unsigned int i, sign, mpilen, nerrors; + + for (i=0; i< noctets; i++) + setbuffer[i] = i; + + mpi_set_buffer( m, setbuffer, noctets, 0); + + getbuffer = mpi_get_buffer( m, &mpilen, &sign ); + + if (mpilen == noctets -1 ) { + nerrors = 0; + for (i=0;i0) + printf("FAIL: got %d different values!\n", nerrors); + else printf("PASSED: mpi_get/set_buffer\n"); + } + + mpi_free(m); + xfree(setbuffer); + xfree(getbuffer); +} + +void test_dirty_float_rng( int nruns ) { + int i, status; + float dirty; + + printf("Running test for smg rng dirty float with %d runs\n", nruns); + for (i=0; i0 ? "OK" : "FAIL"); + } +} + +void test_ieee_float_rng( int nruns ) { + int i, status; + float ieee; + + printf("Running test for smg rng ieee 745/1985 float with %d runs\n", nruns); + for (i=0; i0 ? "OK" : "FAIL"); + } +} + +void test_uint32_rng( int nruns ) { + int i, status; + uint32_t n; + + printf("Running test for smg rng unsigned int32 with %d runs\n", nruns); + for (i=0; i0 ? "OK" : "FAIL"); + } +} + +void test_uint64_rng( int nruns ) { + int i, status; + uint64_t n; + + printf("Running test for smg rng unsigned int64 with %d runs\n", nruns); + for (i=0; i0 ? "OK" : "FAIL"); + } +} + + +int main(int ac, char **av) +{ + int nruns; + int id; + FILE *fk; + FILE *fout; + + if (ac<2) { + printf("Usage: %s number_of_runs/octets [testID]\n", av[0]); + return -1; + } + nruns = atoi(av[1]); + + if (ac < 3) + id = -1; + else + id = atoi(av[2]); + + switch ( id ) { + case 0: + printf("Timing entropy source...\n"); + time_entropy_source(nruns, 4096); + break; + case 1: + test_entropy_output(nruns, "entropy_source_output.txt"); + break; + case 2: + /* tests on miller-rabin */ + /* a few primes (decimal): 65537, 116447, 411949103, 20943302231 */ + test_is_composite(nruns, "0x10001", 0); + test_is_composite(nruns, "0x1C6DF", 0); + test_is_composite(nruns, "0x188DD82F", 0); + test_is_composite(nruns, "0x4E0516E57", 0); + /* a few mersenne primes (decimal): 2^13 - 1 = 8191, 2^17 - 1 = 131071, 2^31 - 1 = 2147483647 */ + test_is_composite(nruns, "0x1FFF", 0); + test_is_composite(nruns, "0x1FFFF", 0); + test_is_composite(nruns, "0x7FFFFFFF", 0); + /* a few carmichael numbers, in decimal: 561, 60977817398996785 */ + test_is_composite(nruns, "0x231", 1); + test_is_composite(nruns, "0xD8A300793EEF31", 1); + /* an even number */ + test_is_composite(nruns, "0x15A9E672864B1E", 1); + /* a phuctor-found non-prime public exponent: 170141183460469231731687303715884105731 */ + test_is_composite(nruns, "0x80000000000000000000000000000003", 1); + break; + case 3: + time_mr(nruns); + break; + case 4: + test_rpng(nruns); + break; + case 5: + time_rpng(nruns); + break; + case 6: + fk = fopen("keys.asc", "a"); + if ( fk == NULL ) + err("Failed to open file keys.asc!"); + fout = fopen("check_keys.asc", "a"); + if ( fout == NULL ) { + fclose(fk); + err("Failed to open file keys_check.asc!"); + } + test_rsa(nruns, fk, fout); + fclose(fk); + fclose(fout); + break; + case 7: + test_rsa_exp(); + break; + case 8: + time_rsa_gen(nruns); + break; + case 9: + test_oaep_encr_decr(nruns); + break; + case 10: + test_mpi_buffer(); + break; + case 11: + test_dirty_float_rng(nruns); + break; + case 12: + test_ieee_float_rng(nruns); + break; + case 13: + test_uint32_rng(nruns); + break; + case 14: + test_uint64_rng(nruns); + break; + default: + printf("Current test ids:\n"); + printf("0 for timing entropy source\n"); + printf("1 for entropy output test\n"); + printf("2 for is_composite (Miller-Rabin) test\n"); + printf("3 for timing Miller-Rabin\n"); + printf("4 for random prime number generator test\n"); + printf("5 for timing random prime number generator\n"); + printf("6 for testing rsa key pair generation and use; \ +writes to keys.asc and check_keys.asc\n"); + printf("7 for testing rsa exponentiation (fixed data)\n"); + printf("8 for timing rsa key pair generator\n"); + printf("9 for oaep encrypt/decrypt\n"); + printf("10 for testing mpi_set/get_buffer\n"); + printf("11 for testing smg_rng dirty float\n"); + printf("12 for testing smg_rng ieee 745/1985 float\n"); + printf("13 for testing smg_rng uint32 \n"); + printf("14 for testing smg_rng uint64 \n"); + } + + return 0; +} diff -uNr a/smg_comms/rsa/truerandom.c b/smg_comms/rsa/truerandom.c --- a/smg_comms/rsa/truerandom.c false +++ b/smg_comms/rsa/truerandom.c 234021f88c073c4c0e719125e55546a98351a2cf0df584701ff19a9e8d9ea5b134fd9fdbcc24cd412c56802099a2929b608c41d3acf7e8fb545eb1c04f8bdf9f @@ -0,0 +1,176 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include "smg_rsa.h" + + +int set_usb_attribs(int fd, int speed) { + struct termios tty; + if (tcgetattr(fd, &tty) < 0) { + return -1; + } + + /* input and output speeds */ + cfsetospeed(&tty, (speed_t)speed); + cfsetispeed(&tty, (speed_t)speed); + + /* raw */ + tty.c_lflag &= ~(ECHO | ECHOE | ECHOK); + tty.c_oflag &= ~OPOST; + + /* read at least one octet at a time; BLOCK until at least VMIN octets read */ + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 0; + + if (tcsetattr(fd, TCSAFLUSH, &tty) != 0) + return -1; + + return 0; +} + +int open_entropy_source(char* source_name) { + int in, err; + + in = open(source_name, O_RDONLY | O_NOCTTY | O_NDELAY); + if (in == -1) { + printf("ERROR: failure to open entropy source %s: %s\n", source_name, strerror(errno)); + return in; //failed to access entropy source + } + + fcntl(in, F_SETFL, 0); + + err = set_usb_attribs(in, B115200); + if (err==-1) { + printf("Error setting attributes on %s: %s\n", source_name, strerror(errno)); + return err; + } + + return in; //source opened, return its descriptor +} + +int get_random_octets_from(int noctets, unsigned char *out, int from) { + + int nread; + int total = 0; + + while (total < noctets) { + errno = 0; + nread = read(from, out+total, noctets-total); + //on interrupt received just try again + if (nread == -1 && errno == EINTR) + continue; + //on error condition abort + if (errno != 0 && (nread == -1 || nread == 0)) { + printf("Error reading from entropy source %s after %d read: %s\n", ENTROPY_SOURCE, total, strerror(errno)); + return total; //total read so far + } + + if (nread > 0) + total = total + nread; + } + return total; //return number of octets read +} + +int get_random_octets(int noctets, unsigned char *out) { + int in; + int nread = 0; + + in = open_entropy_source(ENTROPY_SOURCE); + if (in > 0) { + nread = get_random_octets_from(noctets, out, in); + close(in); + } + return nread; +} + +int rng_dirty_float(float *n) { + int status; /* for aborting in case of error */ + uint32_t r; /* a random value on 32 bits */ + uint32_t maxval = 0xffffffff; /* maximum value on 32 bits */ + + /* obtain a random number on 32 bits using ENTROPY_SOURCE */ + status = rng_uint32( &r ); + if ( status < 0 ) + return status; + + /* calculate and assign the floating-point random value as (r*1.0)/max val */ + /* multiplication by 1.0 IS NEEDED to do float division rather than int div*/ + *n = ( r * 1.0 ) / maxval; + + return 1; +} + +int rng_float_754_1985(float *n) { + /* Single float ieee 754/1985 has 23 bits that can be set for the mantissa + * (and one implicit bit=1). + * Full single float ieee 754/1985 representation takes 4 octets in total. + */ + int noctets = 4; /* number of octets to read from ENTROPY_SOURCE */ + int nread; /* number of octets *read* from ENTROPY_SOURCE */ + unsigned char bits[ noctets ]; /* the random bits from ENTROPY_SOURCE */ + int oSignExp, oExpM;/* offsets for sign+exponent octet, exponent+mantissa*/ + + /* obtain random bits */ + nread = get_random_octets( noctets, bits ); + + if (nread != noctets ) + return -1; /* something wrong at reading from ENTROPY_SOURCE, abort */ + + /* set offsets for bit diddling depending on endianness of iron */ + if (is_bigendian()) { + oSignExp = 0; + oExpM = 1; + } + else { + oSignExp = 3; + oExpM = 2; + } + + /* set sign=0; exponent=127; explicit mantissa = random bits (23 bits) */ + *(bits+oExpM) = *(bits+2) | 0x80; /* one bit of exponent set */ + *(bits+oSignExp) = 0x3f; /* sign=0; exponent bits for 127 */ + + /* now copy the bits to the result var (i.e. as a float's representation */ + memcpy( n, bits, noctets ); + return 1; +} + +int rng_uint32( uint32_t *n ) { + int noctets = 4; /* 32 bits aka 4 octets to read from ENTROPY_SOURCE */ + int nread; /* the number of octets read from ENTROPY_SOURCE */ + unsigned char bits[ noctets ]; /* for storing the bits from ENTROPY_SOURCE */ + + /* read random 32 bits from ENTROPY_SOURCE */ + nread = get_random_octets( noctets, bits ); + if ( nread != noctets ) + return -1; + + /* copy the random bits to n, to be interpreted as uint32 */ + /* endianness is irrelevant here - the bits are random anyway */ + memcpy( n, bits, noctets ); + + return 1; +} + +int rng_uint64( uint64_t *n ) { + int noctets = 8; /* 64 bits aka 8 octets to read from ENTROPY_SOURCE */ + int nread; /* the number of octets read from ENTROPY_SOURCE */ + unsigned char bits[ noctets ]; /* for storing the bits from ENTROPY_SOURCE */ + + /* read random 64 bits from ENTROPY_SOURCE */ + nread = get_random_octets( noctets, bits ); + if ( nread != noctets ) + return -1; + + /* copy the random bits to n, to be interpreted as uint64 */ + /* endianness is irrelevant here - the bits are random anyway */ + memcpy( n, bits, noctets ); + + return 1; +} diff -uNr a/smg_comms/smg_comms.gpr b/smg_comms/smg_comms.gpr --- a/smg_comms/smg_comms.gpr 5834abb16df880d02ac7208fb19a1c2cb14cad43afa73537246d0734d9a845f156f5519bc93d2df74aa479611fc015e5f5a62023025606e5c2e43cfe894730dd +++ b/smg_comms/smg_comms.gpr 1ef7799c9abe4df9e1beb1903c3ea0eba7b9af7407de48e0a8556933a600490bed4815f14da7ae5554209ee93e01a55bb5479ecddda7560e590c9768cde955a2 @@ -2,6 +2,8 @@ -- prototype implementation of S.MG communication protocol -- http://trilema.com/2018/euloras-communication-protocol-restated/ +with "c_wrappers/c_wrappers.gpr"; + project SMG_comms is type Mode_Type is ("debug", "release");