first shot for a libinfnoise approach
This commit is contained in:
		| @@ -1,7 +1,6 @@ | ||||
| GIT_VERSION := $(shell git --no-pager describe --tags --always) | ||||
| GIT_COMMIT  := $(shell git rev-parse --verify HEAD) | ||||
| GIT_DATE    := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only)) | ||||
| BUILD_DATE  := $(shell date --iso=seconds) | ||||
|  | ||||
| PREFIX = $(DESTDIR)/usr/local | ||||
|  | ||||
| @@ -9,7 +8,6 @@ CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -I Keccak -I /usr/include/libftdi1 \ | ||||
|  -DGIT_VERSION=\"$(GIT_VERSION)\"\ | ||||
|  -DGIT_COMMIT=\"$(GIT_COMMIT)\"\ | ||||
|  -DGIT_DATE=\"$(GIT_DATE)\"\ | ||||
|  -DBUILD_DATE=\"$(BUILD_DATE)\" | ||||
|  | ||||
| FOUND = $(shell ldconfig -p | grep --silent libftdi.so && echo found) | ||||
| ifeq ($(FOUND), found) | ||||
| @@ -18,13 +16,22 @@ else | ||||
| 	FTDI=	-lftdi1 | ||||
| endif | ||||
|  | ||||
| all: infnoise | ||||
| all: libinfnoise.a infnoise | ||||
|  | ||||
| infnoise: infnoise.c infnoise.h healthcheck.c writeentropy.c daemon.c Keccak/KeccakF-1600-reference.c Keccak/brg_endian.h | ||||
| 	$(CC) $(CFLAGS) -o infnoise infnoise.c healthcheck.c writeentropy.c daemon.c Keccak/KeccakF-1600-reference.c $(FTDI) -lm -lrt | ||||
| infnoise: infnoise.c infnoise.h libinfnoise.a healthcheck.c writeentropy.c daemon.c | ||||
| 	$(CC) $(CFLAGS) -o infnoise infnoise.c writeentropy.c healthcheck.c daemon.c $(FTDI) -lm -lrt -L . -linfnoise | ||||
|  | ||||
| libinfnoise.a: libinfnoise.c libinfnoise.h healthcheck.c healthcheck.h Keccak/brg_endian.h Keccak/KeccakF-1600-reference.c | ||||
| 	$(CC) $(CFLAGS) -c libinfnoise.c libinfnoise.h healthcheck.c Keccak/KeccakF-1600-reference.c $(FTDI) -lm | ||||
| 	ar rcs libinfnoise.a libinfnoise.o healthcheck.o KeccakF-1600-reference.o | ||||
|  | ||||
| libs: libinfnoise.a | ||||
|  | ||||
| libinfnoise-example: libinfnoise.c libinfnoise.h | ||||
| 	$(CC) $(CFLAGS) -D LIB_EXAMPLE_PROGRAM -o libinfnoise-example libinfnoise.c libinfnoise.h healthcheck.c writeentropy.c daemon.c Keccak/KeccakF-1600-reference.c $(FTDI) -lm -lrt | ||||
|  | ||||
| clean: | ||||
| 	$(RM) infnoise | ||||
| 	$(RM) infnoise *.o *.a libinfnoise-example | ||||
|  | ||||
| install: | ||||
| 	install -d $(PREFIX)/sbin | ||||
|   | ||||
| @@ -24,7 +24,7 @@ confirmed. | ||||
| #include <stdlib.h> | ||||
| #include <math.h> | ||||
| #include <time.h> | ||||
| #include "infnoise.h" | ||||
| #include "libinfnoise.h" | ||||
|  | ||||
| #define INM_MIN_DATA 80000u | ||||
| #define INM_MIN_SAMPLE_SIZE 100u | ||||
| @@ -91,11 +91,11 @@ static void resetStats(void) { | ||||
| // Initialize the health check.  N is the number of bits used to predict the next bit. | ||||
| // At least 8 bits must be used, and no more than 30.  In general, we should use bits | ||||
| // large enough so that INM output will be uncorrelated with bits N samples back in time. | ||||
| bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts) { | ||||
| bool inmHealthCheckStart(uint8_t N, double K, bool debug) { | ||||
|     if(N < 1u || N > 30u) { | ||||
|         return false; | ||||
|     } | ||||
|     inmDebug = opts->debug; | ||||
|     inmDebug = debug; | ||||
|     inmNumBitsOfEntropy = 0u; | ||||
|     inmCurrentProbability = 1.0; | ||||
|     inmK = K; | ||||
|   | ||||
| @@ -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> | ||||
| @@ -13,224 +10,9 @@ | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <ftdi.h> | ||||
| #include "infnoise.h" | ||||
| #include "libinfnoise.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 = | ||||
| @@ -246,13 +28,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; | ||||
| @@ -331,7 +106,6 @@ int main(int argc, char **argv) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // read environment variables, not overriding command line options | ||||
|     if (opts.serial == NULL) { | ||||
|         if (getenv("INFNOISE_SERIAL") != NULL) { | ||||
| @@ -367,31 +141,44 @@ int main(int argc, char **argv) | ||||
| 	printf("GIT VERSION - %s\n", GIT_VERSION); | ||||
| 	printf("GIT COMMIT  - %s\n", GIT_COMMIT); | ||||
| 	printf("GIT DATE    - %s\n", GIT_DATE); | ||||
| 	printf("BUILD DATE  - %s\n", BUILD_DATE); | ||||
| 	return 0; | ||||
|     } | ||||
|  | ||||
|     char *message; | ||||
|     if (opts.listDevices) { | ||||
| 	listUSBDevices(&ftdic); | ||||
|         struct inm_devlist *device_list; | ||||
|         device_list = malloc(sizeof(struct inm_devlist)); | ||||
|  | ||||
|         if(!listUSBDevices(&ftdic, &device_list, &message)) { | ||||
|             fputs(message, stderr); | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         struct inm_devlist_node *tmp; | ||||
|         for ( tmp = device_list->head; tmp != NULL; tmp=tmp->next) { | ||||
|             if (tmp->device->serial != NULL) { | ||||
|                 printf("%s\n", tmp->device->serial); | ||||
|             } | ||||
|             //tmp = tmp->next; | ||||
|         } | ||||
| 	return 0; | ||||
|     } | ||||
|  | ||||
|     // Optionally run in the background and optionally write a PID-file | ||||
|     startDaemon(&opts); | ||||
|  | ||||
|     if(opts.devRandom) { | ||||
|         inmWriteEntropyStart(BUFLEN/8u, &opts); | ||||
|     if (opts.devRandom) { | ||||
|         inmWriteEntropyStart(BUFLEN/8u, opts.debug); | ||||
|     } | ||||
|  | ||||
|     if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, &opts)) { | ||||
|         fputs("Can't intialize health checker\n", stderr); | ||||
|     if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, opts.debug)) { | ||||
|         fputs("Can't initialize 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)) { | ||||
| @@ -429,7 +216,9 @@ int main(int argc, char **argv) | ||||
|             uint32_t entropy = extractBytes(bytes, inBuf); | ||||
|             if(!opts.noOutput && inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { | ||||
|                 uint64_t prevTotalBytesWritten = totalBytesWritten; | ||||
|                 totalBytesWritten += processBytes(keccakState, bytes, entropy, &opts); | ||||
|                 totalBytesWritten += processBytes(keccakState, bytes, NULL, entropy, opts.raw, | ||||
|                                                   opts.devRandom, opts.outputMultiplier, opts.noOutput); | ||||
|  | ||||
|                 if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) { | ||||
|                     fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten); | ||||
|                 } | ||||
|   | ||||
| @@ -2,34 +2,6 @@ | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| // Required accuracy of estimated vs measured entropy in health monitor | ||||
| #define INM_ACCURACY 1.03 | ||||
|  | ||||
| // The FT240X has a 512 byte buffer.  Must be multiple of 64 | ||||
| // We also write this in one go to the Keccak sponge, which is at most 1600 bits | ||||
| #define BUFLEN 512u | ||||
|  | ||||
| // This is how many previous bits are used to predict the next bit from the INM | ||||
| #define PREDICTION_BITS 14u | ||||
|  | ||||
| // This is the maximum time we allow to pass to perform the I/O operations, since long | ||||
| // delays can reduce entropy from the INM. | ||||
| #define MAX_MICROSEC_FOR_SAMPLES 5000u | ||||
|  | ||||
| // This is the gain of each of the two op-amp stages in the INM | ||||
| #define DESIGN_K 1.84 | ||||
|  | ||||
| #define BITMODE_SYNCBB 0x4 | ||||
|  | ||||
| // This defines which pins on the FT240X are used | ||||
| #define COMP1 1u | ||||
| #define COMP2 4u | ||||
| #define SWEN1 2u | ||||
| #define SWEN2 0u | ||||
|  | ||||
| // All data bus bits of the FT240X are outputs, except COMP1 and COMP2 | ||||
| #define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2)) | ||||
|  | ||||
| // Structure for parsed command line options | ||||
| struct opt_struct { | ||||
| 	uint32_t outputMultiplier; // We output all the entropy when outputMultiplier == 0 | ||||
| @@ -46,9 +18,9 @@ struct opt_struct { | ||||
| 	char *serial;		// Name of selected device | ||||
| }; | ||||
|  | ||||
| bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts); | ||||
| void inmHealthCheckStop(void); | ||||
| bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even); | ||||
| //bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts); | ||||
| //void inmHealthCheckStop(void); | ||||
| /*bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even); | ||||
| bool inmHealthCheckOkToUseData(void); | ||||
| double inmHealthCheckEstimateK(void); | ||||
| double inmHealthCheckEstimateEntropyPerBit(void); | ||||
| @@ -59,7 +31,10 @@ void inmWriteEntropyStart(uint32_t bufLen, struct opt_struct *opts); | ||||
| void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy); | ||||
| void inmWaitForPoolToHaveRoom(void); | ||||
| void inmDumpStats(void); | ||||
| */ | ||||
| void startDaemon(struct opt_struct *opts); | ||||
| bool isSuperUser(void); | ||||
|  | ||||
| extern double inmK, inmExpectedEntropyPerBit; | ||||
|  | ||||
| //extern double inmK, inmExpectedEntropyPerBit; | ||||
|  | ||||
|   | ||||
							
								
								
									
										404
									
								
								software/libinfnoise.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										404
									
								
								software/libinfnoise.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,404 @@ | ||||
| /* Driver for the Infinite Noise Multiplier USB stick */ | ||||
|  | ||||
| // 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> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <ftdi.h> | ||||
| #include "libinfnoise.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. | ||||
| 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(); | ||||
| } | ||||
|  | ||||
| // Return the difference in the times as a double in microseconds. | ||||
| 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; | ||||
| } | ||||
|  | ||||
| // Write the bytes to either stdout, or /dev/random. | ||||
| void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom) { | ||||
|     if(!writeDevRandom) { | ||||
|         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 cryptographic keys. | ||||
| uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uint32_t entropy, bool raw, | ||||
|         bool writeDevRandom, uint32_t outputMultiplier, bool noOutput) { | ||||
|     //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(raw) { | ||||
|         // In raw mode, we just output raw data from the INM. | ||||
|         if (!noOutput) { | ||||
|             outputBytes(bytes, BUFLEN/8u, entropy, writeDevRandom); | ||||
|         } else { | ||||
|             memcpy(result, bytes, BUFLEN/8u * sizeof(uint8_t)); | ||||
|             //result=bytes; | ||||
| 	} | ||||
|         return BUFLEN/8u; | ||||
|     } | ||||
|  | ||||
|     // Note that BUFLEN has to be less than 1600 by enough to make the sponge secure, | ||||
|     // since outputting 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 squeezing data out to ensure 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(outputMultiplier == 0u) { | ||||
|         // Output all the bytes of entropy we have | ||||
|         KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u); | ||||
|         outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom); | ||||
|         return entropy/8u; | ||||
|     } // todo: write to result array | ||||
|  | ||||
|     // Output 256*outputMultipler bits. | ||||
|     uint32_t numBits = 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; | ||||
|         } | ||||
| 	if (!noOutput) { | ||||
|             outputBytes(dataOut, bytesToWrite, entropyThisTime, writeDevRandom); | ||||
| 	} else { | ||||
|             // append data in result array until we have finished squeezing the keccak sponge | ||||
| 	    // its important to have an result array of the approriate size: outputMultiplier*32 | ||||
|             fprintf(stderr, "bytes written: %d\n", bytesWritten); | ||||
|             fprintf(stderr, "bytes to write: %d\n", bytesToWrite); | ||||
|  | ||||
|             //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work | ||||
|             // alternative: loop through dataOut and append array elements to result.. | ||||
|             for (uint32_t i =0; i < bytesToWrite; i++ ) { | ||||
|                  fprintf(stderr, "                 result[%d] = dataOut[%d];\n", bytesWritten + i, i); | ||||
|                  result[bytesWritten + i] = dataOut[i]; | ||||
|             } | ||||
| 	} | ||||
|         bytesWritten += bytesToWrite; | ||||
|         numBits -= bytesToWrite*8u; | ||||
|         entropy -= entropyThisTime; | ||||
|         if(numBits > 0u) { | ||||
|             KeccakPermutation(keccakState); | ||||
|         } | ||||
|     } | ||||
|     if(bytesWritten != outputMultiplier*(256u/8u)) { | ||||
|         fprintf(stderr, "Internal error outputing bytes\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|     fprintf(stderr, "bytes written: %d\n", bytesWritten); | ||||
|     return bytesWritten; | ||||
| } | ||||
|  | ||||
| void add_to_list(struct inm_devlist **list, struct infnoise_device **dev) { | ||||
|     struct inm_devlist_node *tmp = malloc(sizeof(struct inm_devlist_node ) ); | ||||
|     tmp->device = (*dev); | ||||
|     printf("added serial1: %s\n", (*dev)->serial); | ||||
|     tmp->next = (*list)->head; | ||||
|     printf("added serial2: %s\n", tmp->device->serial); | ||||
|     (*list)->head = tmp; | ||||
|     printf("added serial3: %s\n", (*list)->head->device->serial); | ||||
| } | ||||
|  | ||||
| // Return a list of all infinite noise multipliers found. | ||||
| bool listUSBDevices(struct ftdi_context *ftdic, struct inm_devlist **result, char** message) { | ||||
|     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()) { | ||||
|             *message = "Can't find Infinite Noise Multiplier.  Try running as super user?\n"; | ||||
|         } else { | ||||
|             *message = "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()) { | ||||
|                 *message = "Can't find Infinite Noise Multiplier.  Try running as super user?\n"; | ||||
|             } | ||||
|             //todo: fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); | ||||
| 	    return false; | ||||
|        	} | ||||
|  | ||||
| 	// build struct of device descriptor & add to list | ||||
|         printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); | ||||
|  | ||||
| 	struct infnoise_device *result_dev = malloc(sizeof(struct infnoise_device)); | ||||
|  | ||||
| 	result_dev->index = i; | ||||
|         result_dev->manufacturer = manufacturer; | ||||
|         result_dev->product = description; | ||||
|         result_dev->serial = serial; | ||||
|  | ||||
|         //printf("debug: %s\n", result_dev); | ||||
|         add_to_list(result, &result_dev); | ||||
|  | ||||
|     struct inm_devlist_node *tmp; | ||||
|     for ( tmp = (*result)->head; tmp != NULL; tmp=tmp->next) { | ||||
|         if (tmp->device->serial != NULL) { | ||||
|             printf("%s\n", tmp->device->serial); | ||||
|         } | ||||
|            //tmp = tmp->next; | ||||
|         } | ||||
|  | ||||
|        	curdev = curdev->next; | ||||
|     } | ||||
|     struct inm_devlist_node *tmp; | ||||
|     for ( tmp = (*result)->head; tmp != NULL; tmp=tmp->next) { | ||||
|         if (tmp->device->serial != NULL) { | ||||
|             printf("%s\n", tmp->device->serial); | ||||
|         } | ||||
|            //tmp = tmp->next; | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| // Initialize the Infinite Noise Multiplier USB interface. | ||||
| 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) { | ||||
| 		*message = "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; | ||||
| } | ||||
|  | ||||
| uint64_t readData(struct ftdi_context *ftdic, uint8_t *keccakState, uint8_t *result, bool raw, uint32_t outputMultiplier, bool debug) { | ||||
|     // 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); | ||||
|     } | ||||
|  | ||||
|     uint64_t totalBytesWritten = 0u; | ||||
|     struct timespec start; | ||||
|     clock_gettime(CLOCK_REALTIME, &start); | ||||
|  | ||||
|     // write clock signal | ||||
|     if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { | ||||
|         fputs("USB write failed\n", stderr); | ||||
|         return -1; | ||||
|     } | ||||
|     // and read 512 byte from the internal buffer (in synchronous bitbang mode) | ||||
|     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(inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { | ||||
|             uint64_t prevTotalBytesWritten = totalBytesWritten; | ||||
|             totalBytesWritten += processBytes(keccakState, bytes, result, entropy, raw, false, outputMultiplier, true); | ||||
|             fprintf(stderr, "bw3: %lu\n", (unsigned long)totalBytesWritten); | ||||
|  | ||||
|             if(debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) { | ||||
|                 fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return totalBytesWritten; | ||||
| } | ||||
|  | ||||
| #ifdef LIB_EXAMPLE_PROGRAM | ||||
| // example use of libinfnoise | ||||
| int main() { | ||||
|     // initialize health check | ||||
|     if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, false)) { | ||||
|         fputs("Can't initialize health checker\n", stderr); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     // initialize keccak | ||||
|     KeccakInitialize(); | ||||
|     uint8_t keccakState[KeccakPermutationSizeInBytes]; | ||||
|     KeccakInitializeState(keccakState); | ||||
|  | ||||
|     // initialize USB | ||||
|     struct ftdi_context ftdic; | ||||
|     char *message; | ||||
|     char *serial=NULL; // use any device, can be set to a specific serial | ||||
|     if(!initializeUSB(&ftdic, &message, serial)) { | ||||
|         // Sometimes have to do it twice - not sure why | ||||
|         if(!initializeUSB(&ftdic, &message, serial)) { | ||||
|             fputs(message, stderr); | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     uint64_t totalBytesWritten = 0u; | ||||
|  | ||||
|     // parameters for readData(..): | ||||
|     bool rawOutput = true; | ||||
|     uint32_t multiplier = 10u; | ||||
|     bool debug = false; | ||||
|  | ||||
|     // calculate output size based on the parameters: | ||||
|     // when using the multiplier, we need a result array of multiplier*32 bytes - otherwise the full buffer size (512 bytes) | ||||
|     uint32_t resultSize; | ||||
|     if (multiplier == 0 || rawOutput == true) { | ||||
|         resultSize = BUFLEN; | ||||
|     } else { | ||||
|         resultSize = multiplier*32; | ||||
|     } | ||||
|     fprintf(stderr, "%d\n", resultSize); | ||||
|  | ||||
|     // read and print | ||||
|     while (totalBytesWritten < 100000) { | ||||
|         fprintf(stderr, "%lu\n", (unsigned long)totalBytesWritten); | ||||
|         uint8_t result[resultSize]; | ||||
|         //uint8_t *result = malloc(resultSize * sizeof(uint8_t)); // array to hold the (whitened) result | ||||
|  | ||||
|         uint64_t bytesWritten = 0u; | ||||
|         bytesWritten = readData(&ftdic, keccakState, result, rawOutput, multiplier, debug); | ||||
|         fprintf(stderr, "bw2: %lu\n", (unsigned long)bytesWritten); | ||||
|  | ||||
| 	totalBytesWritten += bytesWritten; | ||||
|         fwrite(result, 1, bytesWritten, stdout); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										111
									
								
								software/libinfnoise.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								software/libinfnoise.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
| #include <ftdi.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
|  | ||||
|  | ||||
| #define INFNOISE_VENDOR_ID 0x0403 | ||||
| #define INFNOISE_PRODUCT_ID 0x6015 | ||||
|  | ||||
| // Required accuracy of estimated vs measured entropy in health monitor | ||||
| #define INM_ACCURACY 1.03 | ||||
|  | ||||
| // The FT240X has a 512 byte buffer.  Must be multiple of 64 | ||||
| // We also write this in one go to the Keccak sponge, which is at most 1600 bits | ||||
| #define BUFLEN 512u | ||||
|  | ||||
| // This is how many previous bits are used to predict the next bit from the INM | ||||
| #define PREDICTION_BITS 14u | ||||
|  | ||||
| // This is the maximum time we allow to pass to perform the I/O operations, since long | ||||
| // delays can reduce entropy from the INM. | ||||
| #define MAX_MICROSEC_FOR_SAMPLES 5000u | ||||
|  | ||||
| // This is the gain of each of the two op-amp stages in the INM | ||||
| #define DESIGN_K 1.84 | ||||
|  | ||||
| #define BITMODE_SYNCBB 0x4 | ||||
|  | ||||
| // This defines which pins on the FT240X are used | ||||
| #define COMP1 1u | ||||
| #define COMP2 4u | ||||
| #define SWEN1 2u | ||||
| #define SWEN2 0u | ||||
|  | ||||
| // All data bus bits of the FT240X are outputs, except COMP1 and COMP2 | ||||
| #define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2)) | ||||
|  | ||||
| // Structure for parsed command line options | ||||
| struct opt_struct { | ||||
| 	uint32_t outputMultiplier; // We output all the entropy when outputMultiplier == 0 | ||||
| 	bool daemon;		// Run as daemon? | ||||
| 	bool debug;		// Print debugging info? | ||||
| 	bool devRandom;		// Feed /dev/random? | ||||
| 	bool noOutput;		// Supress output? | ||||
| 	bool listDevices;	// List possible USB-devices? | ||||
| 	bool help;		// Show help | ||||
| 	bool none;		// set to true when no valid arguments where detected | ||||
| 	bool raw;		// No whitening? | ||||
| 	bool version;		// Show version | ||||
| 	char *pidFileName;	// Name of optional PID-file | ||||
| 	char *serial;		// Name of selected device | ||||
| }; | ||||
|  | ||||
| // struct for ftdi_device_descriptor | ||||
| struct infnoise_device { | ||||
| 	uint8_t index; | ||||
| 	char *manufacturer; | ||||
| 	char *product; | ||||
| 	char *serial; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct inm_devlist_node | ||||
| { | ||||
|     struct infnoise_device *device; | ||||
|     struct inm_devlist_node *next; | ||||
| }; | ||||
|  | ||||
| struct inm_devlist | ||||
| { | ||||
|     struct inm_devlist_node *head; | ||||
| }; | ||||
|  | ||||
| // struct for list of devices | ||||
| struct infnoise_device_list { | ||||
| 	struct infnoise_device device; | ||||
| 	struct infnoise_device_list * next; | ||||
| }; | ||||
|  | ||||
| bool inmHealthCheckStart(uint8_t N, double K, bool debug); | ||||
| void inmHealthCheckStop(void); | ||||
| bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even); | ||||
| bool inmHealthCheckOkToUseData(void); | ||||
| double inmHealthCheckEstimateK(void); | ||||
| double inmHealthCheckEstimateEntropyPerBit(void); | ||||
| uint32_t inmGetEntropyLevel(void); | ||||
| void inmClearEntropyLevel(void); | ||||
| bool inmEntropyOnTarget(uint32_t entropy, uint32_t bits); | ||||
| void inmWriteEntropyStart(uint32_t bufLen, bool debug); | ||||
| void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy); | ||||
| void inmWaitForPoolToHaveRoom(void); | ||||
| void inmDumpStats(void); | ||||
| void startDaemon(struct opt_struct *opts); | ||||
| bool isSuperUser(void); | ||||
|  | ||||
| extern double inmK, inmExpectedEntropyPerBit; | ||||
| struct timespec; | ||||
| double diffTime(struct timespec *start, struct timespec *end); | ||||
| uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf); | ||||
| void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom); | ||||
| bool listUSBDevices(struct ftdi_context *ftdic, struct inm_devlist **result, char** message); | ||||
| bool initializeUSB(struct ftdi_context* ftdic, char **message, char *serial); | ||||
| uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uint32_t entropy, bool raw, | ||||
|         bool writeDevRandom, uint32_t outputMultiplier, bool noOutput); | ||||
							
								
								
									
										
											BIN
										
									
								
								software/libinfnoise.h.gch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								software/libinfnoise.h.gch
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user