diff -uNr a/eucrypt/mpi/include/mpi.h b/eucrypt/mpi/include/mpi.h --- a/eucrypt/mpi/include/mpi.h 295ff95b636878675cdc74b113ee282afb19cabcae79fda85e80de853604148265e1d150697eaa9aa727b02bc4ace33d98c2242fa4122107cd3f5b0dbf3b6bb8 +++ b/eucrypt/mpi/include/mpi.h d86ff3ed23ff796d0c35b550f60142dd5a7242343dcae7ca74558c30b5fec1749aaf6a0207f4bf39df464bcc60ff37a6495965d3e7dad5ad70c0aeb7a7c2a46c @@ -1,5 +1,6 @@ /* 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): @@ -75,6 +76,7 @@ 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); diff -uNr a/eucrypt/mpi/mpiutil.c b/eucrypt/mpi/mpiutil.c --- a/eucrypt/mpi/mpiutil.c 4f010f44b2944a2995791c5a74d41bc1ffbe017c6bcbcefa0655dd33c72cfc6aa547b7bceda6705c629ab707bbd2f260023efae997dd1ec53fd016d22fe1d5f5 +++ b/eucrypt/mpi/mpiutil.c d98f0266d7c1f2466393e4951babe3a7289cf8133821fbaf3bd139383aa5e14fc1cdab87c6329ab6790b250ce9f141b2b7f935804ec43bc5a4933a2932a8178b @@ -1,5 +1,6 @@ /* 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): @@ -477,6 +478,14 @@ 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) diff -uNr a/eucrypt/smg_rsa/include/smg_rsa.h b/eucrypt/smg_rsa/include/smg_rsa.h --- a/eucrypt/smg_rsa/include/smg_rsa.h 69ed0de509c413d6e911966e2e60de118d6d8db4516ac444fec119c08576153246da0f6aa27ddfcfe3398290a93e000c4a4b6f296b452ed3ddfe406660247708 +++ b/eucrypt/smg_rsa/include/smg_rsa.h d3df108b121830777634fa225dd26165762168ee632c81906b9feb22b43017360f77fae03ce53f4eeec2b81eb28249bcc6542d50ae0fec9f3f1c0d33eb6b3c20 @@ -8,6 +8,13 @@ #include "mpi.h" #include "knobs.h" +/* + * These are constants as per TMSR RSA specification, NOT knobs! + * TMSR key length is 4096 bits (512 octets); this means 2 primes of 2048 bits (256 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 = 512; + /*********truerandom.c*********/ /* @@ -63,6 +70,22 @@ */ 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); + #endif /*SMG_RSA*/ diff -uNr a/eucrypt/smg_rsa/primegen.c b/eucrypt/smg_rsa/primegen.c --- a/eucrypt/smg_rsa/primegen.c d5a314baa0f6d77b60210629541a02f8dd8923a03d0003a2005e46dcac8022780577cf2d584bb869fd241a367153854838fbe88b46380914edb6f35946b457dd +++ b/eucrypt/smg_rsa/primegen.c 125731ab93cc7040a8516735c40563958a82ef0484e0f9df9bc60e33225e39bf919d5f6b277421fed43047fa2b2185c0244378c5568a3623674e8b4abb015168 @@ -103,3 +103,47 @@ 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 ); + do { + get_random_octets_from( noctets, p, entropy_source ); + 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/eucrypt/smg_rsa/tests/tests.c b/eucrypt/smg_rsa/tests/tests.c --- a/eucrypt/smg_rsa/tests/tests.c 0eb9fd7240d16b287c06a319d1d170aea9aa046b4f443ff1339f509d8e7b42317425fd369cedb6e7e3d898700ba917b0b56a83305d730a5cd7d5bd09f4809986 +++ b/eucrypt/smg_rsa/tests/tests.c 25364b546a9ec5983239a7c783b316f704c814ebee5778cfa595f14f802e64930b7234ee536e0f69e519bf36b558bea432d62a85d670d0ff62556cc12c6a1dc6 @@ -4,6 +4,7 @@ #include #include #include +#include void err(char *msg) { @@ -30,6 +31,43 @@ printf("ENTROPY source timing: %d kB in %ld seconds, at an average speed of %f kB/s over %d runs of %d octets each\n", nruns*noctets, diff, kbps, nruns, noctets); } +void test_entropy_output(unsigned int noctets, char * filename) { + FILE * out; + int source; + unsigned int nread, total_read, to_read; + const int buffer_length = 1000; + unsigned char buffer[buffer_length]; + + source = open_entropy_source(ENTROPY_SOURCE); + if (source <= 0) + err("unable to access entropy source!"); + + out = fopen(filename, "wb"); + if ( !out ) + err("unable to open output file for test_entropy_output!"); + + printf("TEST_ENTROPY_SOURCE: reading %u octets from %s ", noctets, ENTROPY_SOURCE); + total_read = 0; + while (total_read < noctets) { + to_read = noctets - total_read; + if (to_read > 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; @@ -52,49 +90,161 @@ 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; i 2) - printf("Current test ids: 0 for all, 1 for entropy source test only, 2 for is_composite test only."); - return 0; } diff -uNr a/eucrypt/smg_rsa/truerandom.c b/eucrypt/smg_rsa/truerandom.c --- a/eucrypt/smg_rsa/truerandom.c 72a4c1f55a1ef9d853f44a93f1f5396e63739dc4c1c70017dd3f3d2ea6c7e1b843ce0ca60e5d06ddcc742ecde6f17cdabddbe833f83ad7bea2cebc40b80e332a +++ b/eucrypt/smg_rsa/truerandom.c c2c0caf7b1df0aa3811a718f544a8e2b5aa1909f97876e4f4070d6b01dc55f444a71837e746d58dc9211fcc4e4033e01582ee4b14c9dca898bb9b838cc022347 @@ -16,27 +16,19 @@ return -1; } - //input and output speeds + /* input and output speeds */ cfsetospeed(&tty, (speed_t)speed); cfsetispeed(&tty, (speed_t)speed); - tty.c_cflag |= (CLOCAL | CREAD); //ignore modem controls - tty.c_cflag &= ~CSIZE; - tty.c_cflag |= CS8; //8 bit characters - tty.c_cflag &= ~PARENB; //no parity bit - tty.c_cflag &= ~CSTOPB; //only need 1 stop bit - tty.c_cflag &= ~CRTSCTS; //no hardware flow control + /* raw */ + tty.c_lflag &= ~(ECHO | ECHOE | ECHOK); + tty.c_oflag &= ~OPOST; - //non-canonical mode - tty.c_cflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - tty.c_cflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - tty.c_cflag &= ~OPOST; - - //read at least one octet at a time; timeout 1 tenth of second between octets read + /* read at least one octet at a time; BLOCK until at least VMIN octets read */ tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 1; + tty.c_cc[VTIME] = 0; - if (tcsetattr(fd, TCSANOW, &tty) != 0) + if (tcsetattr(fd, TCSAFLUSH, &tty) != 0) return -1; return 0;