From 4dcf1d81dd8f59d3f0b6a44a1fe8b058257236c0 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 17 Jul 2018 17:12:33 +0200 Subject: [PATCH] refactored outputBytes (/dev/random not working yet) --- software/infnoise.c | 401 +++++++++++++-------------------- software/infnoise.h | 4 + software/libinfnoise.c | 164 +++++++------- software/libinfnoise_private.h | 4 +- 4 files changed, 245 insertions(+), 328 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index f90139f..bd9eea6 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -18,173 +18,81 @@ #include #include "infnoise.h" #include "libinfnoise.h" -#include "libinfnoise_private.h" #include "KeccakF-1600-interface.h" static void initOpts(struct opt_struct *opts) { - opts->outputMultiplier = 0u; - opts->daemon = false; - opts->debug = false; - opts->devRandom = false; - opts->noOutput = false; - opts->listDevices = false; - opts->raw = false; - opts->version = false; - opts->help = false; - opts->none = false; - opts->pidFileName = - opts->serial = NULL; + opts->outputMultiplier = 0u; + opts->daemon = false; + opts->debug = false; + opts->devRandom = false; + opts->noOutput = false; + opts->listDevices = false; + opts->raw = false; + opts->version = false; + opts->help = false; + opts->none = false; + opts->pidFileName = + opts->serial = NULL; } // getopt_long(3) options descriptor -static struct option longopts[] = {{"raw", no_argument, NULL, 'r'}, - {"debug", no_argument, NULL, 'D'}, - {"dev-random", no_argument, NULL, 'R'}, - {"no-output", no_argument, NULL, 'n'}, - {"multiplier", required_argument, NULL, 'm'}, - {"pidfile", required_argument, NULL, 'p'}, - {"serial", required_argument, NULL, 's'}, - {"daemon", no_argument, NULL, 'd'}, - {"list-devices", no_argument, NULL, 'l'}, - {"version", no_argument, NULL, 'v'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, 0}}; +static struct option longopts[] = { + {"raw", no_argument, NULL, 'r'}, + {"debug", no_argument, NULL, 'D'}, + {"dev-random", no_argument, NULL, 'R'}, + {"no-output", no_argument, NULL, 'n'}, + {"multiplier", required_argument, NULL, 'm'}, + {"pidfile", required_argument, NULL, 'p'}, + {"serial", required_argument, NULL, 's'}, + {"daemon", no_argument, NULL, 'd'}, + {"list-devices", no_argument, NULL, 'l'}, + {"version", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}}; -// -//// Write the bytes to either stdout, or /dev/random. -//bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message) { -// if(!writeDevRandom) -// { -// if(fwrite(bytes, 1, length, stdout) != length) { -// *message = "Unable to write output from Infinite Noise Multiplier"; -// return false; -// } -// } else { -//#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) -// // quell compiler warning about unused variable. -// static int devRandomFD = -1; -// (void)entropy; -// -// if (devRandomFD < 0) -// devRandomFD = open("/dev/random",O_WRONLY); -// if (devRandomFD < 0) { -// *message = "Unable to open random(4)"; -// return false; -// }; -// // we are not trapping EINT and EAGAIN; as the random(4) driver seems -// // to not treat partial writes as not an error. So we think that comparing -// // to length is fine. -// // -// if (write(devRandomFD, bytes, length) != length) { -// *message = "Unable to write output from Infinite Noise Multiplier to random(4)"; -// return false; -// } -//#endif -//#if defined(__APPLE__) -// *message = "macOS doesn't support writes to entropy pool"; -// entropy = 0; // suppress warning -// return false; -//#endif -//#ifdef LINUX -// inmWaitForPoolToHaveRoom(); -// inmWriteEntropyToPool(bytes, length, entropy); -//#endif -// } -// return true; -//} -// -//uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, -// bool raw, bool writeDevRandom, uint32_t outputMultiplier, bool noOutput, -// char **message, bool *errorFlag) { -// //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) { -// if (!outputBytes(bytes, BUFLEN/8u, entropy, writeDevRandom, message)) { -// *errorFlag = true; -// return 0; // write failed -// } -// } else { -// if (result != NULL) { -// memcpy(result, bytes, BUFLEN/8u * sizeof(uint8_t)); -// } -// } -// 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); -// if (!noOutput) { -// if (!outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom, message)) { -// *errorFlag = true; -// return 0; -// } -// } else { -// if (result != NULL) { -// memcpy(result, dataOut, entropy/8u * sizeof(uint8_t)); -// } -// } -// return entropy/8u; -// } -// -// // 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) { -// if (!outputBytes(dataOut, bytesToWrite, entropyThisTime, writeDevRandom, message)) { -// *errorFlag = true; -// return 0; -// } -// } else { -// //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work? -// // alternative: loop through dataOut and append array elements to result.. -// if (result != NULL) { -// for (uint32_t i =0; i < bytesToWrite; i++ ) { -// result[bytesWritten + i] = dataOut[i]; -// } -// } -// } -// bytesWritten += bytesToWrite; -// numBits -= bytesToWrite*8u; -// entropy -= entropyThisTime; -// if(numBits > 0u) { -// KeccakPermutation(keccakState); -// } -// } -// if(bytesWritten != outputMultiplier*(256u/8u)) { -// *message = "Internal error outputing bytes"; -// *errorFlag = true; -// return 0; -// } -// return bytesWritten; -//} + +// Write the bytes to either stdout, or /dev/random. + +bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message) { + if (!writeDevRandom) { + if (fwrite(bytes, 1, length, stdout) != length) { + *message = "Unable to write output from Infinite Noise Multiplier"; + return false; + } + } else { +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) + // quell compiler warning about unused variable. + static int devRandomFD = -1; + (void) entropy; + + if (devRandomFD < 0) + devRandomFD = open("/dev/random", O_WRONLY); + if (devRandomFD < 0) { + *message = "Unable to open random(4)"; + return false; + }; + // we are not trapping EINT and EAGAIN; as the random(4) driver seems + // to not treat partial writes as not an error. So we think that comparing + // to length is fine. + // + if (write(devRandomFD, bytes, length) != length) { + *message = "Unable to write output from Infinite Noise Multiplier to random(4)"; + return false; + } +#endif +#if defined(__APPLE__) + *message = "macOS doesn't support writes to entropy pool"; + entropy = 0; // suppress warning + return false; +#endif +#ifdef LINUX + inmWaitForPoolToHaveRoom(); + inmWriteEntropyToPool(bytes, length, entropy); +#endif + } + return true; +} int main(int argc, char **argv) { struct ftdi_context ftdic; @@ -196,78 +104,78 @@ int main(int argc, char **argv) { // Process arguments while ((ch = getopt_long(argc, argv, "rDRnm:p:s:dlvh", longopts, NULL)) != - -1) { + -1) { switch (ch) { - case 'r': - opts.raw = true; - break; - case 'D': - opts.debug = true; - break; - case 'R': - opts.devRandom = true; - break; - case 'n': - opts.noOutput = true; - break; - case 'm': - multiplierAssigned = true; - int tmpOutputMult = atoi(optarg); - if (tmpOutputMult < 0) { - fputs("Multiplier must be >= 0\n", stderr); - return 1; - } - opts.outputMultiplier = tmpOutputMult; - break; - case 'p': - opts.pidFileName = optarg; - if (opts.pidFileName == NULL || !strcmp("", opts.pidFileName)) { - fputs("--pidfile without file name\n", stderr); - return 1; - } - break; - case 's': - opts.serial = optarg; - if (opts.serial == NULL || !strcmp("", opts.serial)) { - fputs("--serial without value\n", stderr); - return 1; - } - break; - case 'd': - opts.daemon = true; - break; - case 'l': - opts.listDevices = true; - break; - case 'v': - opts.version = true; - break; - case 'h': - opts.help = true; - break; - default: - opts.help = true; - opts.none = true; + case 'r': + opts.raw = true; + break; + case 'D': + opts.debug = true; + break; + case 'R': + opts.devRandom = true; + break; + case 'n': + opts.noOutput = true; + break; + case 'm': + multiplierAssigned = true; + int tmpOutputMult = atoi(optarg); + if (tmpOutputMult < 0) { + fputs("Multiplier must be >= 0\n", stderr); + return 1; + } + opts.outputMultiplier = tmpOutputMult; + break; + case 'p': + opts.pidFileName = optarg; + if (opts.pidFileName == NULL || !strcmp("", opts.pidFileName)) { + fputs("--pidfile without file name\n", stderr); + return 1; + } + break; + case 's': + opts.serial = optarg; + if (opts.serial == NULL || !strcmp("", opts.serial)) { + fputs("--serial without value\n", stderr); + return 1; + } + break; + case 'd': + opts.daemon = true; + break; + case 'l': + opts.listDevices = true; + break; + case 'v': + opts.version = true; + break; + case 'h': + opts.help = true; + break; + default: + opts.help = true; + opts.none = true; } } if (opts.help) { fputs("Usage: infnoise [options]\n" - "Options are:\n" - " -D, --debug - turn on some debug output\n" - " -R, --dev-random - write entropy to /dev/random instead of " - "stdout\n" - " -r, --raw - do not whiten the output\n" - " -m, --multiplier - write 256 bits * value for each 512 bits written to\n" - " the Keccak sponge. Default of 0 means write all the entropy.\n" - " -n, --no-output - do not write random output data\n" - " -p, --pidfile - write process ID to file\n" - " -d, --daemon - run in the background\n" - " -s, --serial - use specified device\n" - " -l, --list-devices - list available devices\n" - " -v, --version - show version information\n" - " -h, --help - this help output\n", - stdout); + "Options are:\n" + " -D, --debug - turn on some debug output\n" + " -R, --dev-random - write entropy to /dev/random instead of " + "stdout\n" + " -r, --raw - do not whiten the output\n" + " -m, --multiplier - write 256 bits * value for each 512 bits written to\n" + " the Keccak sponge. Default of 0 means write all the entropy.\n" + " -n, --no-output - do not write random output data\n" + " -p, --pidfile - write process ID to file\n" + " -d, --daemon - run in the background\n" + " -s, --serial - use specified device\n" + " -l, --list-devices - list available devices\n" + " -v, --version - show version information\n" + " -h, --help - this help output\n", + stdout); if (opts.none) { return 1; } else { @@ -284,7 +192,7 @@ int main(int argc, char **argv) { if (opts.debug == false) { if (getenv("INFNOISE_DEBUG") != NULL) { - if (!strcmp("true",getenv("INFNOISE_DEBUG"))) { + if (!strcmp("true", getenv("INFNOISE_DEBUG"))) { opts.debug = true; } } @@ -302,7 +210,7 @@ int main(int argc, char **argv) { } } - if(!multiplierAssigned && opts.devRandom) { + if (!multiplierAssigned && opts.devRandom) { opts.outputMultiplier = 2u; // Don't throw away entropy when writing to /dev/random unless told to do so } @@ -316,7 +224,7 @@ int main(int argc, char **argv) { char *message = "no data?"; bool errorFlag = false; if (opts.listDevices) { - if(!listUSBDevices(&ftdic, &message)) { + if (!listUSBDevices(&ftdic, &message)) { fputs(message, stderr); return 1; } @@ -326,16 +234,16 @@ int main(int argc, char **argv) { if (opts.devRandom) { #ifdef LINUX - inmWriteEntropyStart(BUFLEN/8u, opts.debug); // todo: create method in libinfnoise.h for this? + 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 :-/) #endif #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) - int devRandomFD = open("/dev/random", O_WRONLY); - if(devRandomFD < 0) { - fprintf(stderr, "Unable to open /dev/random\n"); - exit(1); - } - close(devRandomFD); + int devRandomFD = open("/dev/random", O_WRONLY); + if (devRandomFD < 0) { + fprintf(stderr, "Unable to open /dev/random\n"); + exit(1); + } + close(devRandomFD); #endif #if defined(__APPLE__) message = "dev/random not supported on macOS"; @@ -356,33 +264,38 @@ int main(int argc, char **argv) { // when using the multiplier, we need a result array of 32*MULTIPLIER - otherwise 64(BUFLEN/8) bytes uint32_t resultSize; if (opts.outputMultiplier == 0 || opts.raw == true) { - resultSize = BUFLEN/8u; + resultSize = BUFLEN / 8u; } else { - resultSize = opts.outputMultiplier*32u; + resultSize = opts.outputMultiplier * 32u; } // endless loop uint64_t totalBytesWritten = 0u; - while(true) { + while (true) { uint8_t result[resultSize]; uint64_t prevTotalBytesWritten = totalBytesWritten; if (opts.raw) { - totalBytesWritten = readRawData(&ftdic, result, &message, &errorFlag); + totalBytesWritten += readRawData(&ftdic, result, &message, &errorFlag); } else { - totalBytesWritten = readData(&ftdic, result, &message, &errorFlag, opts.outputMultiplier); + totalBytesWritten += readData(&ftdic, result, &message, &errorFlag, opts.outputMultiplier); } - + //totalBytesWritten += readData_private(&ftdic, NULL, &message, &errorFlag, opts.noOutput, opts.raw, opts.outputMultiplier, opts.devRandom); // calling libinfnoise's private readData method if (errorFlag) { fprintf(stderr, "Error: %s\n", message); return 1; } + + if (!opts.noOutput) { // TODO: pass entropy, so we know how much to write to /dev/random - + outputBytes(result, totalBytesWritten - prevTotalBytesWritten, 512, opts.devRandom, &message); + // bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message) { + } - 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; -} +} \ No newline at end of file diff --git a/software/infnoise.h b/software/infnoise.h index 09499ed..b7ddf95 100644 --- a/software/infnoise.h +++ b/software/infnoise.h @@ -24,4 +24,8 @@ struct opt_struct { char *serial; // Name of selected device }; +void inmWriteEntropyStart(uint32_t bufLen, bool debug); +void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy); +void inmWaitForPoolToHaveRoom(void); + void startDaemon(struct opt_struct *opts); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 9f5cca1..c430fd4 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -24,19 +24,20 @@ #endif uint8_t keccakState[KeccakPermutationSizeInBytes]; -bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool keccak, bool debug) { + +bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool keccak, bool debug) { prepareOutputBuffer(); // initialize health check if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) { - *message="Can't initialize health checker"; + *message = "Can't initialize health checker"; return false; } // initialize USB - if(!initializeUSB(ftdic, message, serial)) { + if (!initializeUSB(ftdic, message, serial)) { // Sometimes have to do it twice - not sure why - if(!initializeUSB(ftdic, message, serial)) { + if (!initializeUSB(ftdic, message, serial)) { return false; } } @@ -51,7 +52,7 @@ bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool uint32_t maxWarmupRounds = 500; uint32_t warmupRounds = 0; bool errorFlag = false; - while(!inmHealthCheckOkToUseData()) { + while (!inmHealthCheckOkToUseData()) { readRawData(ftdic, NULL, message, &errorFlag); warmupRounds++; } @@ -64,13 +65,14 @@ bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool } uint8_t outBuf[BUFLEN]; + void prepareOutputBuffer() { uint32_t i; // Endless loop: set SW1EN and SW2EN alternately - for(i = 0u; i < BUFLEN; i++) { + for (i = 0u; i < BUFLEN; i++) { // Alternate Ph1 and Ph2 - outBuf[i] = i & 1? (1 << SWEN2) : (1 << SWEN1); + outBuf[i] = i & 1 ? (1 << SWEN2) : (1 << SWEN1); } } @@ -78,22 +80,23 @@ void prepareOutputBuffer() { // 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, char **message, bool *errorFlag) { inmClearEntropyLevel(); uint32_t i; - for(i = 0u; i < BUFLEN/8u; 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]; + 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; + 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)) { + if (!inmHealthCheckAddBit(evenBit, oddBit, even)) { *message = "Health check of Infinite Noise Multiplier failed!"; *errorFlag = true; return 0; @@ -104,22 +107,27 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro return inmGetEntropyLevel(); } - +// 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 *bytes, uint8_t *result, uint32_t entropy, bool raw, uint32_t outputMultiplier, char **message, bool *errorFlag) { //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 (entropy > inmExpectedEntropyPerBit * BUFLEN / INM_ACCURACY) { + entropy = inmExpectedEntropyPerBit * BUFLEN / INM_ACCURACY; } - if(raw) { + if (raw) { // In raw mode, we just output raw data from the INM. - if (result != NULL) { - memcpy(result, bytes, BUFLEN/8u * sizeof(uint8_t)); - } - return BUFLEN/8u; + if (result != NULL) { + memcpy(result, bytes, BUFLEN / 8u * sizeof (uint8_t)); + } + return BUFLEN / 8u; } // Note that BUFLEN has to be less than 1600 by enough to make the sponge secure, @@ -129,50 +137,49 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, // 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) { + 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); + KeccakExtract(keccakState, dataOut, (entropy + 63u) / 64u); - if (result != NULL) { - memcpy(result, dataOut, entropy/8u * sizeof(uint8_t)); - } - return entropy/8u; + if (result != NULL) { + memcpy(result, dataOut, entropy / 8u * sizeof (uint8_t)); + } + return entropy / 8u; } // Output 256*outputMultipler bits. - uint32_t numBits = outputMultiplier*256u; + uint32_t numBits = outputMultiplier * 256u; uint32_t bytesWritten = 0u; - while(numBits > 0u) { + while (numBits > 0u) { // Write up to 1024 bits at a time. - uint32_t bytesToWrite = 1024u/8u; - if(bytesToWrite > numBits/8u) { - bytesToWrite = numBits/8u; + uint32_t bytesToWrite = 1024u / 8u; + if (bytesToWrite > numBits / 8u) { + bytesToWrite = numBits / 8u; } - KeccakExtract(keccakState, dataOut, bytesToWrite/8u); + KeccakExtract(keccakState, dataOut, bytesToWrite / 8u); uint32_t entropyThisTime = entropy; - if(entropyThisTime > 8u*bytesToWrite) { - entropyThisTime = 8u*bytesToWrite; + if (entropyThisTime > 8u * bytesToWrite) { + entropyThisTime = 8u * bytesToWrite; } - - //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work? - // alternative: loop through dataOut and append array elements to result.. - if (result != NULL) { - for (uint32_t i =0; i < bytesToWrite; i++ ) { - result[bytesWritten + i] = dataOut[i]; - } + //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work? + // alternative: loop through dataOut and append array elements to result.. + if (result != NULL) { + for (uint32_t i = 0; i < bytesToWrite; i++) { + result[bytesWritten + i] = dataOut[i]; } + } bytesWritten += bytesToWrite; - numBits -= bytesToWrite*8u; + numBits -= bytesToWrite * 8u; entropy -= entropyThisTime; - if(numBits > 0u) { + if (numBits > 0u) { KeccakPermutation(keccakState); } } - if(bytesWritten != outputMultiplier*(256u/8u)) { - *message = "Internal error outputing bytes"; + if (bytesWritten != outputMultiplier * (256u / 8u)) { + *message = "Internal error outputting bytes"; *errorFlag = true; return 0; } @@ -181,32 +188,26 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, // 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; + return seconds * 1.0e6 + nanoseconds / 1000.0; } bool isSuperUser(void) { - return (geteuid() == 0); + return (geteuid() == 0); } -// 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. - - // Return a list of all infinite noise multipliers found. + bool listUSBDevices(struct ftdi_context *ftdic, 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; + int i = 0; // search devices int rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); @@ -240,6 +241,7 @@ bool listUSBDevices(struct ftdi_context *ftdic, char** message) { } // 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; @@ -259,7 +261,7 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { *message = "Multiple Infnoise TRNGs found and serial not specified, using the first one!"; } if (ftdi_usb_open(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID) < 0) { - if(!isSuperUser()) { + if (!isSuperUser()) { *message = "Can't open Infinite Noise Multiplier. Try running as super user?"; } else { #ifdef LINUX @@ -276,7 +278,7 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { // serial specified rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial); if (rc < 0) { - if(!isSuperUser()) { + if (!isSuperUser()) { *message = "Can't find Infinite Noise Multiplier. Try running as super user?"; } else { *message = "Can't find Infinite Noise Multiplier with given serial"; @@ -288,52 +290,51 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { // Set high baud rate rc = ftdi_set_baudrate(ftdic, 30000); - if(rc == -1) { + if (rc == -1) { *message = "Invalid baud rate"; return false; - } else if(rc == -2) { + } else if (rc == -2) { *message = "Setting baud rate failed"; return false; - } else if(rc == -3) { + } else if (rc == -3) { *message = "Infinite Noise Multiplier unavailable"; return false; } rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB); - if(rc == -1) { + if (rc == -1) { *message = "Can't enable bit-bang mode"; return false; - } else if(rc == -2) { + } 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) { + if (ftdi_write_data(ftdic, buf, 64) != 64) { *message = "USB write failed"; return false; } - if(ftdi_read_data(ftdic, buf, 64) != 64) { + if (ftdi_read_data(ftdic, buf, 64) != 64) { *message = "USB read failed"; return false; } return true; } - uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag) { - uint8_t inBuf[BUFLEN]; + uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); // write clock signal - if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { + if (ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { *message = "USB write failed"; *errorFlag = true; } // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if(ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { + if (ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { *message = "USB read failed"; *errorFlag = true; } @@ -341,8 +342,8 @@ uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message 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]; + if (us <= MAX_MICROSEC_FOR_SAMPLES) { + uint8_t bytes[BUFLEN / 8u]; uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag); // call health check and process bytes if OK @@ -360,13 +361,13 @@ uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, b clock_gettime(CLOCK_REALTIME, &start); // write clock signal - if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { + if (ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { *message = "USB write failed"; *errorFlag = true; } // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if(ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { + if (ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { *message = "USB read failed"; *errorFlag = true; } @@ -374,8 +375,8 @@ uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, b 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]; + if (us <= MAX_MICROSEC_FOR_SAMPLES) { + uint8_t bytes[BUFLEN / 8u]; uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag); // call health check and process bytes if OK @@ -385,13 +386,14 @@ uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, b } } return 0; - } +} // #ifdef LIB_EXAMPLE_PROGRAM // example use of libinfnoise - with keccak + int main() { - char *serial=NULL; // use any device, can be set to a specific serial + char *serial = NULL; // use any device, can be set to a specific serial // initialize USB struct ftdi_context ftdic; @@ -405,9 +407,9 @@ int main() { // when using the multiplier, we need a result array of 32*MULTIPLIER - otherwise 64(BUFLEN/8) bytes uint32_t resultSize; if (multiplier == 0 || rawOutput == true) { - resultSize = BUFLEN/8u; + resultSize = BUFLEN / 8u; } else { - resultSize = multiplier*32u; + resultSize = multiplier * 32u; } uint64_t totalBytesWritten = 0u; diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 65360ff..69e06a2 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -48,9 +48,7 @@ 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); extern double inmK, inmExpectedEntropyPerBit;