raw
smg_comms_c_wrappers    1 #include <stdio.h>
smg_comms_c_wrappers 2 #include <stdlib.h>
smg_comms_c_wrappers 3 #include <string.h>
smg_comms_c_wrappers 4
smg_comms_c_wrappers 5 #include <fcntl.h>
smg_comms_c_wrappers 6 #include <unistd.h>
smg_comms_c_wrappers 7 #include <termios.h>
smg_comms_c_wrappers 8 #include <errno.h>
smg_comms_c_wrappers 9
smg_comms_c_wrappers 10 #include "smg_rsa.h"
smg_comms_c_wrappers 11
smg_comms_c_wrappers 12
smg_comms_c_wrappers 13 int set_usb_attribs(int fd, int speed) {
smg_comms_c_wrappers 14 struct termios tty;
smg_comms_c_wrappers 15 if (tcgetattr(fd, &tty) < 0) {
smg_comms_c_wrappers 16 return -1;
smg_comms_c_wrappers 17 }
smg_comms_c_wrappers 18
smg_comms_c_wrappers 19 /* input and output speeds */
smg_comms_c_wrappers 20 cfsetospeed(&tty, (speed_t)speed);
smg_comms_c_wrappers 21 cfsetispeed(&tty, (speed_t)speed);
smg_comms_c_wrappers 22
smg_comms_c_wrappers 23 /* raw */
smg_comms_c_wrappers 24 tty.c_lflag &= ~(ECHO | ECHOE | ECHOK);
smg_comms_c_wrappers 25 tty.c_oflag &= ~OPOST;
smg_comms_c_wrappers 26
smg_comms_c_wrappers 27 /* read at least one octet at a time; BLOCK until at least VMIN octets read */
smg_comms_c_wrappers 28 tty.c_cc[VMIN] = 1;
smg_comms_c_wrappers 29 tty.c_cc[VTIME] = 0;
smg_comms_c_wrappers 30
smg_comms_c_wrappers 31 if (tcsetattr(fd, TCSAFLUSH, &tty) != 0)
smg_comms_c_wrappers 32 return -1;
smg_comms_c_wrappers 33
smg_comms_c_wrappers 34 return 0;
smg_comms_c_wrappers 35 }
smg_comms_c_wrappers 36
smg_comms_c_wrappers 37 int open_entropy_source(char* source_name) {
smg_comms_c_wrappers 38 int in, err;
smg_comms_c_wrappers 39
smg_comms_c_wrappers 40 in = open(source_name, O_RDONLY | O_NOCTTY | O_NDELAY);
smg_comms_c_wrappers 41 if (in == -1) {
smg_comms_c_wrappers 42 printf("ERROR: failure to open entropy source %s: %s\n", source_name, strerror(errno));
smg_comms_c_wrappers 43 return in; //failed to access entropy source
smg_comms_c_wrappers 44 }
smg_comms_c_wrappers 45
smg_comms_c_wrappers 46 fcntl(in, F_SETFL, 0);
smg_comms_c_wrappers 47
smg_comms_c_wrappers 48 err = set_usb_attribs(in, B115200);
smg_comms_c_wrappers 49 if (err==-1) {
smg_comms_c_wrappers 50 printf("Error setting attributes on %s: %s\n", source_name, strerror(errno));
smg_comms_c_wrappers 51 return err;
smg_comms_c_wrappers 52 }
smg_comms_c_wrappers 53
smg_comms_c_wrappers 54 return in; //source opened, return its descriptor
smg_comms_c_wrappers 55 }
smg_comms_c_wrappers 56
smg_comms_c_wrappers 57 int get_random_octets_from(int noctets, unsigned char *out, int from) {
smg_comms_c_wrappers 58
smg_comms_c_wrappers 59 int nread;
smg_comms_c_wrappers 60 int total = 0;
smg_comms_c_wrappers 61
smg_comms_c_wrappers 62 while (total < noctets) {
smg_comms_c_wrappers 63 errno = 0;
smg_comms_c_wrappers 64 nread = read(from, out+total, noctets-total);
smg_comms_c_wrappers 65 //on interrupt received just try again
smg_comms_c_wrappers 66 if (nread == -1 && errno == EINTR)
smg_comms_c_wrappers 67 continue;
smg_comms_c_wrappers 68 //on error condition abort
smg_comms_c_wrappers 69 if (errno != 0 && (nread == -1 || nread == 0)) {
smg_comms_c_wrappers 70 printf("Error reading from entropy source %s after %d read: %s\n", ENTROPY_SOURCE, total, strerror(errno));
smg_comms_c_wrappers 71 return total; //total read so far
smg_comms_c_wrappers 72 }
smg_comms_c_wrappers 73
smg_comms_c_wrappers 74 if (nread > 0)
smg_comms_c_wrappers 75 total = total + nread;
smg_comms_c_wrappers 76 }
smg_comms_c_wrappers 77 return total; //return number of octets read
smg_comms_c_wrappers 78 }
smg_comms_c_wrappers 79
smg_comms_c_wrappers 80 int get_random_octets(int noctets, unsigned char *out) {
smg_comms_c_wrappers 81 int in;
smg_comms_c_wrappers 82 int nread = 0;
smg_comms_c_wrappers 83
smg_comms_c_wrappers 84 in = open_entropy_source(ENTROPY_SOURCE);
smg_comms_c_wrappers 85 if (in > 0) {
smg_comms_c_wrappers 86 nread = get_random_octets_from(noctets, out, in);
smg_comms_c_wrappers 87 close(in);
smg_comms_c_wrappers 88 }
smg_comms_c_wrappers 89 return nread;
smg_comms_c_wrappers 90 }
smg_comms_c_wrappers 91
smg_comms_c_wrappers 92 int rng_dirty_float(float *n) {
smg_comms_c_wrappers 93 int status; /* for aborting in case of error */
smg_comms_c_wrappers 94 uint32_t r; /* a random value on 32 bits */
smg_comms_c_wrappers 95 uint32_t maxval = 0xffffffff; /* maximum value on 32 bits */
smg_comms_c_wrappers 96
smg_comms_c_wrappers 97 /* obtain a random number on 32 bits using ENTROPY_SOURCE */
smg_comms_c_wrappers 98 status = rng_uint32( &r );
smg_comms_c_wrappers 99 if ( status < 0 )
smg_comms_c_wrappers 100 return status;
smg_comms_c_wrappers 101
smg_comms_c_wrappers 102 /* calculate and assign the floating-point random value as (r*1.0)/max val */
smg_comms_c_wrappers 103 /* multiplication by 1.0 IS NEEDED to do float division rather than int div*/
smg_comms_c_wrappers 104 *n = ( r * 1.0 ) / maxval;
smg_comms_c_wrappers 105
smg_comms_c_wrappers 106 return 1;
smg_comms_c_wrappers 107 }
smg_comms_c_wrappers 108
smg_comms_c_wrappers 109 int rng_float_754_1985(float *n) {
smg_comms_c_wrappers 110 /* Single float ieee 754/1985 has 23 bits that can be set for the mantissa
smg_comms_c_wrappers 111 * (and one implicit bit=1).
smg_comms_c_wrappers 112 * Full single float ieee 754/1985 representation takes 4 octets in total.
smg_comms_c_wrappers 113 */
smg_comms_c_wrappers 114 int noctets = 4; /* number of octets to read from ENTROPY_SOURCE */
smg_comms_c_wrappers 115 int nread; /* number of octets *read* from ENTROPY_SOURCE */
smg_comms_c_wrappers 116 unsigned char bits[ noctets ]; /* the random bits from ENTROPY_SOURCE */
smg_comms_c_wrappers 117 int oSignExp, oExpM;/* offsets for sign+exponent octet, exponent+mantissa*/
smg_comms_c_wrappers 118
smg_comms_c_wrappers 119 /* obtain random bits */
smg_comms_c_wrappers 120 nread = get_random_octets( noctets, bits );
smg_comms_c_wrappers 121
smg_comms_c_wrappers 122 if (nread != noctets )
smg_comms_c_wrappers 123 return -1; /* something wrong at reading from ENTROPY_SOURCE, abort */
smg_comms_c_wrappers 124
smg_comms_c_wrappers 125 /* set offsets for bit diddling depending on endianness of iron */
smg_comms_c_wrappers 126 if (is_bigendian()) {
smg_comms_c_wrappers 127 oSignExp = 0;
smg_comms_c_wrappers 128 oExpM = 1;
smg_comms_c_wrappers 129 }
smg_comms_c_wrappers 130 else {
smg_comms_c_wrappers 131 oSignExp = 3;
smg_comms_c_wrappers 132 oExpM = 2;
smg_comms_c_wrappers 133 }
smg_comms_c_wrappers 134
smg_comms_c_wrappers 135 /* set sign=0; exponent=127; explicit mantissa = random bits (23 bits) */
smg_comms_c_wrappers 136 *(bits+oExpM) = *(bits+2) | 0x80; /* one bit of exponent set */
smg_comms_c_wrappers 137 *(bits+oSignExp) = 0x3f; /* sign=0; exponent bits for 127 */
smg_comms_c_wrappers 138
smg_comms_c_wrappers 139 /* now copy the bits to the result var (i.e. as a float's representation */
smg_comms_c_wrappers 140 memcpy( n, bits, noctets );
smg_comms_c_wrappers 141 return 1;
smg_comms_c_wrappers 142 }
smg_comms_c_wrappers 143
smg_comms_c_wrappers 144 int rng_uint32( uint32_t *n ) {
smg_comms_c_wrappers 145 int noctets = 4; /* 32 bits aka 4 octets to read from ENTROPY_SOURCE */
smg_comms_c_wrappers 146 int nread; /* the number of octets read from ENTROPY_SOURCE */
smg_comms_c_wrappers 147 unsigned char bits[ noctets ]; /* for storing the bits from ENTROPY_SOURCE */
smg_comms_c_wrappers 148
smg_comms_c_wrappers 149 /* read random 32 bits from ENTROPY_SOURCE */
smg_comms_c_wrappers 150 nread = get_random_octets( noctets, bits );
smg_comms_c_wrappers 151 if ( nread != noctets )
smg_comms_c_wrappers 152 return -1;
smg_comms_c_wrappers 153
smg_comms_c_wrappers 154 /* copy the random bits to n, to be interpreted as uint32 */
smg_comms_c_wrappers 155 /* endianness is irrelevant here - the bits are random anyway */
smg_comms_c_wrappers 156 memcpy( n, bits, noctets );
smg_comms_c_wrappers 157
smg_comms_c_wrappers 158 return 1;
smg_comms_c_wrappers 159 }
smg_comms_c_wrappers 160
smg_comms_c_wrappers 161 int rng_uint64( uint64_t *n ) {
smg_comms_c_wrappers 162 int noctets = 8; /* 64 bits aka 8 octets to read from ENTROPY_SOURCE */
smg_comms_c_wrappers 163 int nread; /* the number of octets read from ENTROPY_SOURCE */
smg_comms_c_wrappers 164 unsigned char bits[ noctets ]; /* for storing the bits from ENTROPY_SOURCE */
smg_comms_c_wrappers 165
smg_comms_c_wrappers 166 /* read random 64 bits from ENTROPY_SOURCE */
smg_comms_c_wrappers 167 nread = get_random_octets( noctets, bits );
smg_comms_c_wrappers 168 if ( nread != noctets )
smg_comms_c_wrappers 169 return -1;
smg_comms_c_wrappers 170
smg_comms_c_wrappers 171 /* copy the random bits to n, to be interpreted as uint64 */
smg_comms_c_wrappers 172 /* endianness is irrelevant here - the bits are random anyway */
smg_comms_c_wrappers 173 memcpy( n, bits, noctets );
smg_comms_c_wrappers 174
smg_comms_c_wrappers 175 return 1;
smg_comms_c_wrappers 176 }