diff -uNr a/eucrypt/README b/eucrypt/README --- a/eucrypt/README 0f1e1e6138e6ac1f44446b24c9fcef78dab67b5ac2186aea170b507eb33839533699c37c897dafab1bad76f35bf5b98c80dea90b2102dfab6580e2ccd1e6a9ce +++ b/eucrypt/README aa729907e4754118467efcbf8912694f0889f10d1a1406a142568d3b159c43ee5e11b44715f525d3b4c8b94ff90ecd0602bf627dae800ff339bb8486d6ec4004 @@ -32,3 +32,6 @@ RSA implementation using TMSR specification. Implemented in C. +6. smg_rng + This provides methods for obtaining random uint32_t, uint64_t, "dirty" float (between 0 and 1), IEEE 754/1985 float (between 1 and 2) using random bits from FG. + At the moment, this code is within smg_rsa (truerandom.c in particular) although it is likely to be extracted in the future as a standalone library/component pending release of vtools that are aware of code *moves* as opposed to del/add only. 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 8ce351dc40192ae3425d230be59b8b487b9a206d2ae0747f87b09e00ccdf14898876877c68a6ea9e2c382b90220401b1ec4925f59906e77895c4a499827751f1 +++ b/eucrypt/smg_rsa/include/smg_rsa.h dab95b2f666390284b7ba75171f6836e16847e0b910755599c439f5792e1cdf83ca43c198d03a19491faf213313d34635c373bfc13a97ed432c1ca4faaefdf18 @@ -8,6 +8,12 @@ #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 TMSR RSA specification, NOT knobs! * TMSR key length is 4096 bits (512 octets); this means 2 primes of 2048 bits (256 octets) each. @@ -82,6 +88,73 @@ */ 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*********/ /* diff -uNr a/eucrypt/smg_rsa/tests/tests.c b/eucrypt/smg_rsa/tests/tests.c --- a/eucrypt/smg_rsa/tests/tests.c 01945e4cad02ccc3811194a69cb62904b862f6a07e6ef4c7801e4d702a9c076ab3ce0056349e7121d64212b73511400c5d28580c400ffad7e71014f753e4295a +++ b/eucrypt/smg_rsa/tests/tests.c 89b1c405d92e249341bdc0bddc5a98d8ae8dd0349e04a165063d938f01df557a057be544c51b0efb6d72d505f1424a1aa3a6d7957e83f229711677240123e2fd @@ -601,6 +601,51 @@ 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; @@ -680,6 +725,18 @@ 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"); @@ -694,6 +751,10 @@ 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/eucrypt/smg_rsa/truerandom.c b/eucrypt/smg_rsa/truerandom.c --- a/eucrypt/smg_rsa/truerandom.c c2c0caf7b1df0aa3811a718f544a8e2b5aa1909f97876e4f4070d6b01dc55f444a71837e746d58dc9211fcc4e4033e01582ee4b14c9dca898bb9b838cc022347 +++ b/eucrypt/smg_rsa/truerandom.c 234021f88c073c4c0e719125e55546a98351a2cf0df584701ff19a9e8d9ea5b134fd9fdbcc24cd412c56802099a2929b608c41d3acf7e8fb545eb1c04f8bdf9f @@ -89,3 +89,88 @@ 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; +}