#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; }