Fix merge
This commit is contained in:
		| @@ -3,9 +3,6 @@ | ||||
| // Required to include clock_gettime | ||||
| #define _POSIX_C_SOURCE 200809L | ||||
|  | ||||
| #define INFNOISE_VENDOR_ID 0x0403 | ||||
| #define INFNOISE_PRODUCT_ID 0x6015 | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
| @@ -16,229 +13,17 @@ | ||||
| #include <sys/types.h> | ||||
| #include <ftdi.h> // requires <sys/types.h> | ||||
| #include "infnoise.h" | ||||
| #include "libinfnoise.h" | ||||
| #include "libinfnoise_private.h" | ||||
| #include "KeccakF-1600-interface.h" | ||||
|  | ||||
| // Extract the INM output from the data received.  Basically, either COMP1 or COMP2 | ||||
| // changes, not both, so alternate reading bits from them.  We get 1 INM bit of output | ||||
| // per byte read.  Feed bits from the INM to the health checker.  Return the expected | ||||
| // bits of entropy. | ||||
| static uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf) { | ||||
|     inmClearEntropyLevel(); | ||||
|     uint32_t i; | ||||
|     for(i = 0u; i < BUFLEN/8u; i++) { | ||||
|         uint32_t j; | ||||
|         uint8_t byte = 0u; | ||||
|         for(j = 0u; j < 8u; j++) { | ||||
|             uint8_t val = inBuf[i*8u + j]; | ||||
|             uint8_t evenBit = (val >> COMP2) & 1u; | ||||
|             uint8_t oddBit = (val >> COMP1) & 1u; | ||||
|             bool even = j & 1u; // Use the even bit if j is odd | ||||
|             uint8_t bit = even? evenBit : oddBit; | ||||
|             byte = (byte << 1u) | bit; | ||||
|             // This is a good place to feed the bit from the INM to the health checker. | ||||
|             if(!inmHealthCheckAddBit(evenBit, oddBit, even)) { | ||||
|                 fputs("Health check of Infinite Noise Multiplier failed!\n", stderr); | ||||
|                 exit(1); | ||||
|             } | ||||
|         } | ||||
|         bytes[i] = byte; | ||||
|     } | ||||
|     return inmGetEntropyLevel(); | ||||
| } | ||||
|  | ||||
| // Write the bytes to either stdout, or /dev/random. | ||||
| static void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, struct opt_struct *opts) { | ||||
|     if(!opts->devRandom) { | ||||
|         if(fwrite(bytes, 1, length, stdout) != length) { | ||||
|             fputs("Unable to write output from Infinite Noise Multiplier\n", stderr); | ||||
|             exit(1); | ||||
|         } | ||||
|     } else { | ||||
|         inmWaitForPoolToHaveRoom(); | ||||
|         inmWriteEntropyToPool(bytes, length, entropy); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Whiten the output, if requested, with a Keccak sponge.  Output bytes only if the health | ||||
| // checker says it's OK.  Using outputMultiplier > 1 is a nice way to generate a lot more | ||||
| // cryptographically secure pseudo-random data than the INM generates.  If | ||||
| // outputMultiplier is 0, we output only as many bits as we measure in entropy. | ||||
| // This allows a user to generate hundreds of MiB per second if needed, for use | ||||
| // as cryptogrpahic keys. | ||||
| static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entropy, struct opt_struct* opts) { | ||||
|     //Use the lower of the measured entropy and the provable lower bound on | ||||
|     //average entropy. | ||||
|     if(entropy > inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY) { | ||||
|         entropy = inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY; | ||||
|     } | ||||
|     if(opts->raw) { | ||||
|         // In raw mode, we just output raw data from the INM. | ||||
|         outputBytes(bytes, BUFLEN/8u, entropy, opts); | ||||
|         return BUFLEN/8u; | ||||
|     } | ||||
|     // Note that BUFLEN has to be less than 1600 by enough to make the sponge secure, | ||||
|     // since outputing all 1600 bits would tell an attacker the Keccak state, allowing | ||||
|     // him to predict any further output, when outputMultiplier > 1, until the next call | ||||
|     // to processBytes.  All 512 bits are absorbed before sqeezing data out to insure that | ||||
|     // we instantly recover (reseed) from a state compromise, which is when an attacker | ||||
|     // gets a snapshot of the keccak state.  BUFLEN must be a multiple of 64, since | ||||
|     // Keccak-1600 uses 64-bit "lanes". | ||||
|     KeccakAbsorb(keccakState, bytes, BUFLEN/64u); | ||||
|     uint8_t dataOut[16u*8u]; | ||||
|     if(opts->outputMultiplier == 0u) { | ||||
|         // Output all the bytes of entropy we have | ||||
|         KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u); | ||||
|         outputBytes(dataOut, entropy/8u, entropy & 0x7u, opts); | ||||
|         return entropy/8u; | ||||
|     } | ||||
|  | ||||
|     // Output 256*outputMultipler bytes. | ||||
|     uint32_t numBits = opts->outputMultiplier*256u; | ||||
|     uint32_t bytesWritten = 0u; | ||||
|     while(numBits > 0u) { | ||||
|         // Write up to 1024 bits at a time. | ||||
|         uint32_t bytesToWrite = 1024u/8u; | ||||
|         if(bytesToWrite > numBits/8u) { | ||||
|             bytesToWrite = numBits/8u; | ||||
|         } | ||||
|         KeccakExtract(keccakState, dataOut, bytesToWrite/8u); | ||||
|         uint32_t entropyThisTime = entropy; | ||||
|         if(entropyThisTime > 8u*bytesToWrite) { | ||||
|             entropyThisTime = 8u*bytesToWrite; | ||||
|         } | ||||
|         outputBytes(dataOut, bytesToWrite, entropyThisTime, opts); | ||||
|         bytesWritten += bytesToWrite; | ||||
|         numBits -= bytesToWrite*8u; | ||||
|         entropy -= entropyThisTime; | ||||
|         if(numBits > 0u) { | ||||
|             KeccakPermutation(keccakState); | ||||
|         } | ||||
|     } | ||||
|     if(bytesWritten != opts->outputMultiplier*(256u/8u)) { | ||||
|         fprintf(stderr, "Internal error outputing bytes\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     return bytesWritten; | ||||
| } | ||||
|  | ||||
| // Return a list of all infinite noise multipliers found. | ||||
| static bool listUSBDevices(struct ftdi_context *ftdic) { | ||||
|     ftdi_init(ftdic); | ||||
|  | ||||
|     struct ftdi_device_list *devlist; | ||||
|     struct ftdi_device_list *curdev; | ||||
|     char manufacturer[128], description[128], serial[128]; | ||||
|     int i=0; | ||||
|  | ||||
|     // search devices | ||||
|     int rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); | ||||
|  | ||||
|     if (rc < 0) { | ||||
|         if (!isSuperUser()) { | ||||
|             fprintf(stderr, "Can't find Infinite Noise Multiplier.  Try running as super user?\n"); | ||||
|         } else { | ||||
|             fprintf(stderr, "Can't find Infinite Noise Multiplier\n"); | ||||
|         } | ||||
|     } | ||||
|     for (curdev = devlist; curdev != NULL; i++) { | ||||
|         printf("Device: %d, ", i); | ||||
|         rc = ftdi_usb_get_strings(ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128); | ||||
|         if (rc < 0) { | ||||
|             if (!isSuperUser()) { | ||||
|                 fprintf(stderr, "Can't find Infinite Noise Multiplier.  Try running as super user?\n"); | ||||
|             } | ||||
|             fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); | ||||
| 	    return false; | ||||
|        	} | ||||
|         printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); | ||||
|        	curdev = curdev->next; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| // Initialize the Infinite Noise Multiplier USB interface. | ||||
| static bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { | ||||
|     ftdi_init(ftdic); | ||||
|     struct ftdi_device_list *devlist; | ||||
|  | ||||
|     // search devices | ||||
|     int rc = 0; | ||||
|     if ((rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID)) < 0) { | ||||
|         *message = "Can't find Infinite Noise Multiplier\n"; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // only one found, or no serial given | ||||
|     if (rc >= 0) { | ||||
| 	if (serial == NULL) { | ||||
|             // more than one found AND no serial given | ||||
|             if (rc >= 2) { | ||||
| 		fprintf(stderr,"Multiple Infnoise TRNGs found and serial not specified, using the first one!\n"); | ||||
|             } | ||||
|             if (ftdi_usb_open(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID) < 0) { | ||||
|                 if(!isSuperUser()) { | ||||
|                     *message = "Can't open Infinite Noise Multiplier. Try running as super user?\n"; | ||||
|                 } else { | ||||
|                     *message = "Can't open Infinite Noise Multiplier\n"; | ||||
|                 } | ||||
|                 return false; | ||||
| 	    } | ||||
|         } else { | ||||
|             // serial specified | ||||
|             rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial); | ||||
|             if (rc < 0) { | ||||
|                 if(!isSuperUser()) { | ||||
|                     *message = "Can't find Infinite Noise Multiplier. Try running as super user?\n"; | ||||
|                 } else { | ||||
|                     *message = "Can't find Infinite Noise Multiplier with given serial\n"; | ||||
|                 } | ||||
|                 return false; | ||||
| 	    } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Set high baud rate | ||||
|     rc = ftdi_set_baudrate(ftdic, 30000); | ||||
|     if(rc == -1) { | ||||
|         *message = "Invalid baud rate\n"; | ||||
|         return false; | ||||
|     } else if(rc == -2) { | ||||
|         *message = "Setting baud rate failed\n"; | ||||
|         return false; | ||||
|     } else if(rc == -3) { | ||||
|         *message = "Infinite Noise Multiplier unavailable\n"; | ||||
|         return false; | ||||
|     } | ||||
|     rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB); | ||||
|     if(rc == -1) { | ||||
|         *message = "Can't enable bit-bang mode\n"; | ||||
|         return false; | ||||
|     } else if(rc == -2) { | ||||
|         *message = "Infinite Noise Multiplier unavailable\n"; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Just test to see that we can write and read. | ||||
|     uint8_t buf[64u] = {0u,}; | ||||
|     if(ftdi_write_data(ftdic, buf, 64) != 64) { | ||||
|         *message = "USB write failed\n"; | ||||
|         return false; | ||||
|     } | ||||
|     if(ftdi_read_data(ftdic, buf, 64) != 64) { | ||||
|         *message = "USB read failed\n"; | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static void initOpts(struct opt_struct *opts) { | ||||
| 	opts->outputMultiplier = 0u; | ||||
| 	opts->daemon = | ||||
| 	opts->debug = | ||||
| 	opts->devRandom = | ||||
| 	opts->noOutput = | ||||
| 	opts->listDevices = | ||||
| 	opts->daemon = false; | ||||
| 	opts->debug = false; | ||||
| 	opts->devRandom = false; | ||||
| 	opts->noOutput = false; | ||||
| 	opts->listDevices = false; | ||||
| 	opts->raw = false; | ||||
| 	opts->version = false; | ||||
| 	opts->help = false; | ||||
| @@ -247,13 +32,6 @@ static void initOpts(struct opt_struct *opts) { | ||||
| 	opts->serial = NULL; | ||||
| } | ||||
|  | ||||
| // Return the differnece in the times as a double in microseconds. | ||||
| static double diffTime(struct timespec *start, struct timespec *end) { | ||||
|     uint32_t seconds = end->tv_sec - start->tv_sec; | ||||
|     int32_t nanoseconds = end->tv_nsec - start->tv_nsec; | ||||
|     return seconds*1.0e6 + nanoseconds/1000.0; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     struct ftdi_context ftdic; | ||||
| @@ -332,7 +110,6 @@ int main(int argc, char **argv) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // read environment variables, not overriding command line options | ||||
|     if (opts.serial == NULL) { | ||||
|         if (getenv("INFNOISE_SERIAL") != NULL) { | ||||
| @@ -371,69 +148,44 @@ int main(int argc, char **argv) | ||||
| 	return 0; | ||||
|     } | ||||
|  | ||||
|     char *message = "no data?"; | ||||
|     bool errorFlag = false; | ||||
|     if (opts.listDevices) { | ||||
| 	listUSBDevices(&ftdic); | ||||
|         if(!listUSBDevices(&ftdic, &message)) { | ||||
|             fputs(message, stderr); | ||||
|             return 1; | ||||
|         } | ||||
|         //fputs(message, stdout); // todo: put list of devices to &message and print here, not in libinfnoise | ||||
| 	return 0; | ||||
|     } | ||||
|  | ||||
|     if (opts.devRandom) { | ||||
|         inmWriteEntropyStart(BUFLEN/8u, opts.debug); // todo: create method in libinfnoise.h for this? | ||||
| 	// also todo: check superUser in this mode (it will fail silently if not :-/) | ||||
|     } | ||||
|  | ||||
|     // Optionally run in the background and optionally write a PID-file | ||||
|     startDaemon(&opts); | ||||
|  | ||||
|     if(opts.devRandom) { | ||||
|         inmWriteEntropyStart(BUFLEN/8u, &opts); | ||||
|     } | ||||
|  | ||||
|     if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, &opts)) { | ||||
|         fputs("Can't intialize health checker\n", stderr); | ||||
|         return 1; | ||||
|     } | ||||
|     KeccakInitialize(); | ||||
|     uint8_t keccakState[KeccakPermutationSizeInBytes]; | ||||
|     KeccakInitializeState(keccakState); | ||||
|  | ||||
|     char *message; | ||||
|     if(!initializeUSB(&ftdic, &message, opts.serial)) { | ||||
|         // Sometimes have to do it twice - not sure why | ||||
|         if(!initializeUSB(&ftdic, &message, opts.serial)) { | ||||
|             fputs(message, stderr); | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Endless loop: set SW1EN and SW2EN alternately | ||||
|     uint32_t i; | ||||
|     uint8_t outBuf[BUFLEN], inBuf[BUFLEN]; | ||||
|     for(i = 0u; i < BUFLEN; i++) { | ||||
|         // Alternate Ph1 and Ph2 | ||||
|         outBuf[i] = i & 1?  (1 << SWEN2) : (1 << SWEN1); | ||||
|     // initialize USB device, health check and Keccak state (see libinfnoise) | ||||
|     if (!initInfnoise(&ftdic, opts.serial, &message, !opts.raw, opts.debug)) { | ||||
|         fputs(message, stderr); | ||||
|         return 1; // ERROR | ||||
|     } | ||||
|  | ||||
|     // endless loop | ||||
|     uint64_t totalBytesWritten = 0u; | ||||
|     while(true) { | ||||
|         struct timespec start; | ||||
|         clock_gettime(CLOCK_REALTIME, &start); | ||||
|         uint64_t prevTotalBytesWritten = totalBytesWritten; | ||||
|         totalBytesWritten += readData_private(&ftdic, NULL, &message, &errorFlag, opts.noOutput, opts.raw, opts.outputMultiplier, opts.devRandom); // calling libinfnoise's private readData method | ||||
|  | ||||
|         if(ftdi_write_data(&ftdic, outBuf, BUFLEN) != BUFLEN) { | ||||
|             fputs("USB write failed\n", stderr); | ||||
|         if (errorFlag) { | ||||
|             fprintf(stderr, "Error: %s\n", message); | ||||
|             return 1; | ||||
|         } | ||||
|         if(ftdi_read_data(&ftdic, inBuf, BUFLEN) != BUFLEN) { | ||||
|             fputs("USB read failed\n", stderr); | ||||
|             return 1; | ||||
|         } | ||||
|         struct timespec end; | ||||
|         clock_gettime(CLOCK_REALTIME, &end); | ||||
|         uint32_t us = diffTime(&start, &end); | ||||
|         if(us <= MAX_MICROSEC_FOR_SAMPLES) { | ||||
|             uint8_t bytes[BUFLEN/8u]; | ||||
|             uint32_t entropy = extractBytes(bytes, inBuf); | ||||
|             if(!opts.noOutput && inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { | ||||
|                 uint64_t prevTotalBytesWritten = totalBytesWritten; | ||||
|                 totalBytesWritten += processBytes(keccakState, bytes, entropy, &opts); | ||||
|                 if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) { | ||||
|                     fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) { | ||||
|             fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten); | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user