From e674b38c765e2192ef2aa739081cd4d9605d86c1 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 17 Jul 2018 13:34:34 +0200 Subject: [PATCH 01/17] first step to clean up libinfnoise --- software/infnoise.c | 154 ++++++++++++++++++++++++++++++++- software/libinfnoise.c | 147 +++++++++++++------------------ software/libinfnoise_private.h | 3 +- 3 files changed, 214 insertions(+), 90 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index fcd307b..f90139f 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -51,6 +51,141 @@ static struct option longopts[] = {{"raw", no_argument, NULL, 'r'}, {"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; +//} + int main(int argc, char **argv) { struct ftdi_context ftdic; struct opt_struct opts; @@ -217,11 +352,28 @@ int main(int argc, char **argv) { return 1; // ERROR } + // calculate output size based on the parameters: + // 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; + } else { + resultSize = opts.outputMultiplier*32u; + } + // endless loop uint64_t totalBytesWritten = 0u; while(true) { + uint8_t result[resultSize]; 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 (opts.raw) { + totalBytesWritten = readRawData(&ftdic, result, &message, &errorFlag); + } else { + 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); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index e0460c3..9f5cca1 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -52,9 +52,10 @@ bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool uint32_t warmupRounds = 0; bool errorFlag = false; while(!inmHealthCheckOkToUseData()) { - readData_private(ftdic, NULL, message, &errorFlag, false, true, 0, false); + readRawData(ftdic, NULL, message, &errorFlag); warmupRounds++; } + if (warmupRounds > maxWarmupRounds) { *message = "Unable to collect enough entropy to initialize health checker."; return false; @@ -103,67 +104,10 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro 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. -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; -} - -bool isSuperUser(void) { - 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. uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, - bool raw, bool writeDevRandom, uint32_t outputMultiplier, bool noOutput, + bool raw, uint32_t outputMultiplier, char **message, bool *errorFlag) { //Use the lower of the measured entropy and the provable lower bound on //average entropy. @@ -172,16 +116,9 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, } 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; } @@ -197,16 +134,10 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, 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; } @@ -225,12 +156,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t 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) { @@ -238,7 +164,6 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, result[bytesWritten + i] = dataOut[i]; } } - } bytesWritten += bytesToWrite; numBits -= bytesToWrite*8u; entropy -= entropyThisTime; @@ -254,6 +179,26 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, return bytesWritten; } + +// 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; +} + +bool isSuperUser(void) { + 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); @@ -375,16 +320,41 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { return true; } + uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag) { - return readData_private(ftdic, result, message, errorFlag, false, true, 0, false); + uint8_t inBuf[BUFLEN]; + struct timespec start; + clock_gettime(CLOCK_REALTIME, &start); + + // write clock signal + 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) { + *message = "USB read failed"; + *errorFlag = true; + } + + 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, message, errorFlag); + + // call health check and process bytes if OK + if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { + uint32_t byteswritten = processBytes(bytes, result, entropy, true, 0, message, errorFlag); + return byteswritten; + } + } + return 0; } uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier) { - return readData_private(ftdic, result, message, errorFlag, false, false, outputMultiplier, false); -} - -uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, - bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom) { uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); @@ -410,12 +380,13 @@ uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **me // call health check and process bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { - uint32_t byteswritten = processBytes(bytes, result, entropy, raw, devRandom, outputMultiplier, noOutput, message, errorFlag); + uint32_t byteswritten = processBytes(bytes, result, entropy, false, outputMultiplier, message, errorFlag); return byteswritten; } } return 0; -} + } +// #ifdef LIB_EXAMPLE_PROGRAM // example use of libinfnoise - with keccak diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 1280081..65360ff 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -63,7 +63,8 @@ double diffTime(struct timespec *start, struct timespec *end); uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *errorFlag); bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message); + 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); + uint32_t outputMultiplier, char **message, bool *errorFlag); uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom); From 4dcf1d81dd8f59d3f0b6a44a1fe8b058257236c0 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 17 Jul 2018 17:12:33 +0200 Subject: [PATCH 02/17] 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; From bee31d57cb000920e69348cceaeb4ddaf74e124b Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 17 Jul 2018 17:33:02 +0200 Subject: [PATCH 03/17] rename README --- software/{README => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename software/{README => README.md} (100%) diff --git a/software/README b/software/README.md similarity index 100% rename from software/README rename to software/README.md From f0b407b9c5070a89a98e1c396d1a5728fff7f07e Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 17 Jul 2018 18:08:25 +0200 Subject: [PATCH 04/17] set entropy to 0 --- software/infnoise.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index bd9eea6..d9996a2 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -281,16 +281,13 @@ int main(int argc, char **argv) { 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.noOutput) { // TODO: pass entropy, so we know how much to write to /dev/random. For testing, use 64 instead of 0. + outputBytes(result, totalBytesWritten - prevTotalBytesWritten, 0, opts.devRandom, &message); } if (opts.debug && (1u << 20u)*(totalBytesWritten / (1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten / (1u << 20u))) { From 7b1f6a7965ea8a5f35ed350a32f83d0316e48618 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 24 Jul 2018 09:50:26 +0200 Subject: [PATCH 05/17] instroduce infnoise_context struct --- software/infnoise.c | 17 +++++---- software/infnoise.h | 1 + software/libinfnoise.c | 63 +++++++++++++++++----------------- software/libinfnoise.h | 16 ++++++--- software/libinfnoise_private.h | 8 ++--- 5 files changed, 58 insertions(+), 47 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index d9996a2..d27a6ec 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -95,7 +95,8 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe } int main(int argc, char **argv) { - struct ftdi_context ftdic; + //struct ftdi_context ftdic; + struct infnoise_context context; struct opt_struct opts; int ch; bool multiplierAssigned = false; @@ -224,7 +225,7 @@ int main(int argc, char **argv) { char *message = "no data?"; bool errorFlag = false; if (opts.listDevices) { - if (!listUSBDevices(&ftdic, &message)) { + if (!listUSBDevices(&message)) { fputs(message, stderr); return 1; } @@ -254,9 +255,10 @@ int main(int argc, char **argv) { // Optionally run in the background and optionally write a PID-file startDaemon(&opts); + // initialize USB device, health check and Keccak state (see libinfnoise) - if (!initInfnoise(&ftdic, opts.serial, &message, !opts.raw, opts.debug)) { - fprintf(stderr, "Error: %s\n", message); + if (!initInfnoise(&context, opts.serial, !opts.raw, opts.debug)) { + fprintf(stderr, "Error: %s\n", context.message); return 1; // ERROR } @@ -276,9 +278,9 @@ int main(int argc, char **argv) { uint64_t prevTotalBytesWritten = totalBytesWritten; if (opts.raw) { - totalBytesWritten += readRawData(&ftdic, result, &message, &errorFlag); + totalBytesWritten += readRawData(&context, result); } else { - totalBytesWritten += readData(&ftdic, result, &message, &errorFlag, opts.outputMultiplier); + totalBytesWritten += readData(&context, result, opts.outputMultiplier); } if (errorFlag) { @@ -287,7 +289,8 @@ int main(int argc, char **argv) { } if (!opts.noOutput) { // TODO: pass entropy, so we know how much to write to /dev/random. For testing, use 64 instead of 0. - outputBytes(result, totalBytesWritten - prevTotalBytesWritten, 0, opts.devRandom, &message); + //(next step: use entropyBytes from context struct) + outputBytes(result, totalBytesWritten - prevTotalBytesWritten, 0, opts.devRandom, &message); } if (opts.debug && (1u << 20u)*(totalBytesWritten / (1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten / (1u << 20u))) { diff --git a/software/infnoise.h b/software/infnoise.h index b7ddf95..f713827 100644 --- a/software/infnoise.h +++ b/software/infnoise.h @@ -24,6 +24,7 @@ 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); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index c430fd4..e772360 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -16,7 +16,6 @@ #include #include #include "libinfnoise_private.h" -#include "libinfnoise.h" #include "KeccakF-1600-interface.h" #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) @@ -25,19 +24,19 @@ uint8_t keccakState[KeccakPermutationSizeInBytes]; -bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool keccak, bool debug) { +bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug) { prepareOutputBuffer(); // initialize health check if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) { - *message = "Can't initialize health checker"; + context->message = "Can't initialize health checker"; return false; } // initialize USB - if (!initializeUSB(ftdic, message, serial)) { + if (!initializeUSB(&context->ftdic, &context->message, serial)) { // Sometimes have to do it twice - not sure why - if (!initializeUSB(ftdic, message, serial)) { + if (!initializeUSB(&context->ftdic, &context->message, serial)) { return false; } } @@ -51,14 +50,14 @@ bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool // let healthcheck collect some data uint32_t maxWarmupRounds = 500; uint32_t warmupRounds = 0; - bool errorFlag = false; + //bool errorFlag = false; while (!inmHealthCheckOkToUseData()) { - readRawData(ftdic, NULL, message, &errorFlag); + readRawData(context, NULL); warmupRounds++; } if (warmupRounds > maxWarmupRounds) { - *message = "Unable to collect enough entropy to initialize health checker."; + context->message = "Unable to collect enough entropy to initialize health checker."; return false; } return true; @@ -201,8 +200,10 @@ bool isSuperUser(void) { // Return a list of all infinite noise multipliers found. -bool listUSBDevices(struct ftdi_context *ftdic, char** message) { - ftdi_init(ftdic); +bool listUSBDevices(char** message) { + struct ftdi_context ftdic; + + ftdi_init(&ftdic); struct ftdi_device_list *devlist; struct ftdi_device_list *curdev; @@ -210,7 +211,7 @@ bool listUSBDevices(struct ftdi_context *ftdic, char** message) { int i = 0; // search devices - int rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); + int rc = ftdi_usb_find_all(&ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); if (rc < 0) { if (!isSuperUser()) { @@ -222,7 +223,7 @@ bool listUSBDevices(struct ftdi_context *ftdic, char** message) { for (curdev = devlist; curdev != NULL; i++) { //printf("Device: %d, ", i); - rc = ftdi_usb_get_strings(ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128); + 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?"; @@ -242,7 +243,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) { +bool initializeUSB(struct ftdi_context *ftdic, char **message,char *serial) { ftdi_init(ftdic); struct ftdi_device_list *devlist; @@ -322,21 +323,21 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { return true; } -uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag) { +uint32_t readRawData(struct infnoise_context *context, uint8_t *result) { uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); // write clock signal - if (ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { - *message = "USB write failed"; - *errorFlag = true; + if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) { + context->message = "USB write failed"; + context->errorFlag = true; } // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if (ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { - *message = "USB read failed"; - *errorFlag = true; + if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { + context->message = "USB read failed"; + context->errorFlag = true; } struct timespec end; @@ -344,32 +345,32 @@ uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message uint32_t us = diffTime(&start, &end); if (us <= MAX_MICROSEC_FOR_SAMPLES) { uint8_t bytes[BUFLEN / 8u]; - uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag); + uint32_t entropy = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); // call health check and process bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { - uint32_t byteswritten = processBytes(bytes, result, entropy, true, 0, message, errorFlag); + uint32_t byteswritten = processBytes(bytes, result, entropy, true, 0, &context->message, &context->errorFlag); return byteswritten; } } return 0; } -uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier) { +uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier) { uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); // write clock signal - if (ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) { - *message = "USB write failed"; - *errorFlag = true; + if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) { + context->message = "USB write failed"; + context->errorFlag = true; } // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if (ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) { - *message = "USB read failed"; - *errorFlag = true; + if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { + context->message = "USB read failed"; + context->errorFlag = true; } struct timespec end; @@ -377,11 +378,11 @@ uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, b uint32_t us = diffTime(&start, &end); if (us <= MAX_MICROSEC_FOR_SAMPLES) { uint8_t bytes[BUFLEN / 8u]; - uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag); + uint32_t entropy = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); // call health check and process bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { - uint32_t byteswritten = processBytes(bytes, result, entropy, false, outputMultiplier, message, errorFlag); + uint32_t byteswritten = processBytes(bytes, result, entropy, false, outputMultiplier, &context->message, &context->errorFlag); return byteswritten; } } diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 7ebc5f9..0effff0 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -13,10 +13,18 @@ // We also write this in one go to the Keccak sponge, which is at most 1600 bits #define BUFLEN 512u -bool listUSBDevices(struct ftdi_context *ftdic, char **message); +struct infnoise_context { + struct ftdi_context ftdic; + uint32_t entropyBytes; + char *message; + bool errorFlag; + //uint8_t keccakState[KeccakPermutationSizeInBytes]; +} ; -bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool keccak, bool debug); +bool listUSBDevices(char** message); -uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag); +bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug); -uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier); +uint32_t readRawData(struct infnoise_context *context, uint8_t *result); + +uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier); \ No newline at end of file diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 69e06a2..253f773 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -8,7 +8,7 @@ #endif #include #include - +#include "libinfnoise.h" #define INFNOISE_VENDOR_ID 0x0403 #define INFNOISE_PRODUCT_ID 0x6015 @@ -37,8 +37,6 @@ // All data bus bits of the FT240X are outputs, except COMP1 and COMP2 #define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2)) - - bool inmHealthCheckStart(uint8_t N, double K, bool debug); void inmHealthCheckStop(void); bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even); @@ -53,7 +51,7 @@ void inmDumpStats(void); extern double inmK, inmExpectedEntropyPerBit; -bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial); +bool initializeUSB(struct ftdi_context *ftdic, char **message,char *serial); void prepareOutputBuffer(); struct timespec; @@ -65,4 +63,4 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, bool raw, uint32_t outputMultiplier, char **message, bool *errorFlag); -uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom); +//uint32_t readData_private(struct infnoise_context *context, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom); From 773cf0157510da6ce22e2e4b33ea42f6ac1fe788 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Tue, 24 Jul 2018 18:51:21 +0200 Subject: [PATCH 06/17] finish infnoise_context & start work on listUSBDevices (to return a device list struct) --- software/infnoise.c | 21 +++++++++-------- software/libinfnoise.c | 52 +++++++++++++++++++++++++++--------------- software/libinfnoise.h | 18 +++++++++++---- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index d27a6ec..6dab5d5 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -225,18 +225,22 @@ int main(int argc, char **argv) { char *message = "no data?"; bool errorFlag = false; if (opts.listDevices) { - if (!listUSBDevices(&message)) { - fputs(message, stderr); - return 1; + devlist_node *devlist = listUSBDevices(&message); + devlist_node *curdev; + uint8_t i=0; + for (curdev = devlist; curdev != NULL;i++) { + printf("Manufacturer: %s, Description: %s, Serial: %s\n", curdev->manufacturer, curdev.description, + curdev.serial); + curdev = curdev->next; } - //fputs(message, stdout); // todo: put list of devices to &message and print here, not in libinfnoise + //fputs(message, stdout); // TODO: iterate through infnoise_devlist and print stuff return 0; } if (opts.devRandom) { #ifdef LINUX - 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 :-/) + 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); @@ -288,9 +292,8 @@ int main(int argc, char **argv) { return 1; } - if (!opts.noOutput) { // TODO: pass entropy, so we know how much to write to /dev/random. For testing, use 64 instead of 0. - //(next step: use entropyBytes from context struct) - outputBytes(result, totalBytesWritten - prevTotalBytesWritten, 0, opts.devRandom, &message); + if (!opts.noOutput) { + outputBytes(result, totalBytesWritten - prevTotalBytesWritten, context.entropyThisTime, opts.devRandom, &message); } if (opts.debug && (1u << 20u)*(totalBytesWritten / (1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten / (1u << 20u))) { diff --git a/software/libinfnoise.c b/software/libinfnoise.c index e772360..326f04f 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -200,9 +200,8 @@ bool isSuperUser(void) { // Return a list of all infinite noise multipliers found. -bool listUSBDevices(char** message) { +devlist_node* listUSBDevices(char **message) { struct ftdi_context ftdic; - ftdi_init(&ftdic); struct ftdi_device_list *devlist; @@ -210,7 +209,7 @@ bool listUSBDevices(char** message) { char manufacturer[128], description[128], serial[128]; int i = 0; - // search devices + // search devices int rc = ftdi_usb_find_all(&ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); if (rc < 0) { @@ -221,24 +220,42 @@ bool listUSBDevices(char** message) { } } + devlist_node *return_list =NULL; + devlist_node *current_entry =NULL; + for (curdev = devlist; curdev != NULL; i++) { - //printf("Device: %d, ", i); + if (return_list == NULL) { + *return_list = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); + (*return_list)->id = i; + (*return_list)->serial = serial; + (*return_list)->manufacturer = manufacturer; + (*return_list)->description = description; + current_entry = return_list; + } else { + (*current_entry)->next = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); + current_entry = (*current_entry)->next; + (*current_entry)->id = i; + (*current_entry)->serial = serial; + (*current_entry)->manufacturer = manufacturer; + (*current_entry)->description = description; + } + 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?"; - return false; + *message = "Can't find Infinite Noise Multiplier. Try running as super user?"; + return return_list; } //*message = "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); - return false; + return return_list; } // print to stdout - printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); + //printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); curdev = curdev->next; + //current_node = current_node->next; // ??? } - - return true; + return return_list; } // Initialize the Infinite Noise Multiplier USB interface. @@ -345,12 +362,11 @@ uint32_t readRawData(struct infnoise_context *context, uint8_t *result) { uint32_t us = diffTime(&start, &end); if (us <= MAX_MICROSEC_FOR_SAMPLES) { uint8_t bytes[BUFLEN / 8u]; - uint32_t entropy = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); + context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); // call health check and process bytes if OK - if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { - uint32_t byteswritten = processBytes(bytes, result, entropy, true, 0, &context->message, &context->errorFlag); - return byteswritten; + if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { + return processBytes(bytes, result, context->entropyThisTime, true, 0, &context->message, &context->errorFlag); } } return 0; @@ -378,12 +394,11 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t ou uint32_t us = diffTime(&start, &end); if (us <= MAX_MICROSEC_FOR_SAMPLES) { uint8_t bytes[BUFLEN / 8u]; - uint32_t entropy = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); + context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); // call health check and process bytes if OK - if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) { - uint32_t byteswritten = processBytes(bytes, result, entropy, false, outputMultiplier, &context->message, &context->errorFlag); - return byteswritten; + if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { + return processBytes(bytes, result, context->entropyThisTime, false, outputMultiplier, &context->message, &context->errorFlag); } } return 0; @@ -392,6 +407,7 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t ou #ifdef LIB_EXAMPLE_PROGRAM // example use of libinfnoise - with keccak +// TODO: rewrite! int main() { char *serial = NULL; // use any device, can be set to a specific serial diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 0effff0..267a1aa 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -15,16 +15,26 @@ struct infnoise_context { struct ftdi_context ftdic; - uint32_t entropyBytes; + uint32_t entropyThisTime; char *message; bool errorFlag; //uint8_t keccakState[KeccakPermutationSizeInBytes]; -} ; +}; -bool listUSBDevices(char** message); +struct infnoise_devlist_node { + uint8_t id; + char *manufacturer; + char *description; + char *serial; + struct infnoise_devlist_node *next; +}; + +typedef struct infnoise_devlist_node* devlist_node; + +devlist_node* listUSBDevices(char** message); bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug); uint32_t readRawData(struct infnoise_context *context, uint8_t *result); -uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier); \ No newline at end of file +uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier); From e380194881264c59cf94ba92f65b5dfc0d195e65 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Thu, 26 Jul 2018 09:20:35 +0200 Subject: [PATCH 07/17] untested fix for --list-devices (no device at hand to test right now..) --- software/infnoise.c | 9 ++++----- software/libinfnoise.c | 20 ++++++++++---------- software/libinfnoise.h | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index 6dab5d5..0e323cc 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -225,12 +225,12 @@ int main(int argc, char **argv) { char *message = "no data?"; bool errorFlag = false; if (opts.listDevices) { - devlist_node *devlist = listUSBDevices(&message); - devlist_node *curdev; + devlist_node devlist = listUSBDevices(&message); + devlist_node curdev; uint8_t i=0; for (curdev = devlist; curdev != NULL;i++) { - printf("Manufacturer: %s, Description: %s, Serial: %s\n", curdev->manufacturer, curdev.description, - curdev.serial); + printf("Manufacturer: %s, Description: %s, Serial: %s\n", curdev->manufacturer, curdev->description, + curdev->serial); curdev = curdev->next; } //fputs(message, stdout); // TODO: iterate through infnoise_devlist and print stuff @@ -259,7 +259,6 @@ int main(int argc, char **argv) { // Optionally run in the background and optionally write a PID-file startDaemon(&opts); - // initialize USB device, health check and Keccak state (see libinfnoise) if (!initInfnoise(&context, opts.serial, !opts.raw, opts.debug)) { fprintf(stderr, "Error: %s\n", context.message); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 326f04f..8d9d034 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -200,7 +200,7 @@ bool isSuperUser(void) { // Return a list of all infinite noise multipliers found. -devlist_node* listUSBDevices(char **message) { +devlist_node listUSBDevices(char **message) { struct ftdi_context ftdic; ftdi_init(&ftdic); @@ -220,20 +220,20 @@ devlist_node* listUSBDevices(char **message) { } } - devlist_node *return_list =NULL; + devlist_node return_list =NULL; devlist_node *current_entry =NULL; for (curdev = devlist; curdev != NULL; i++) { if (return_list == NULL) { - *return_list = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); - (*return_list)->id = i; - (*return_list)->serial = serial; - (*return_list)->manufacturer = manufacturer; - (*return_list)->description = description; - current_entry = return_list; + return_list = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); + return_list->id = i; + return_list->serial = serial; + return_list->manufacturer = manufacturer; + return_list->description = description; + *current_entry = return_list; } else { (*current_entry)->next = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); - current_entry = (*current_entry)->next; + *current_entry = (*current_entry)->next; (*current_entry)->id = i; (*current_entry)->serial = serial; (*current_entry)->manufacturer = manufacturer; @@ -251,7 +251,7 @@ devlist_node* listUSBDevices(char **message) { } // print to stdout - //printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); + printf("debug: Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); curdev = curdev->next; //current_node = current_node->next; // ??? } diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 267a1aa..26d867d 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -31,7 +31,7 @@ struct infnoise_devlist_node { typedef struct infnoise_devlist_node* devlist_node; -devlist_node* listUSBDevices(char** message); +devlist_node listUSBDevices(char** message); bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug); From 6d832f1b1282ccc0e7e7a1ebde85cd39a888c427 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Thu, 26 Jul 2018 13:15:30 +0200 Subject: [PATCH 08/17] fix --list-devices (still buggy, but works!) --- software/build-scripts/infnoise-gitian.yml | 181 +++++++++++++++++++++ software/infnoise.c | 13 +- software/libinfnoise.c | 39 ++--- software/libinfnoise.h | 6 +- 4 files changed, 205 insertions(+), 34 deletions(-) create mode 100644 software/build-scripts/infnoise-gitian.yml diff --git a/software/build-scripts/infnoise-gitian.yml b/software/build-scripts/infnoise-gitian.yml new file mode 100644 index 0000000..93ce084 --- /dev/null +++ b/software/build-scripts/infnoise-gitian.yml @@ -0,0 +1,181 @@ +xy--- +name: "infnoise-linux-dev" +enable_cache: true +suites: +- "bionic" +architectures: +- "amd64" +packages: +- "g++-aarch64-linux-gnu" +- "g++-7-aarch64-linux-gnu" +- "gcc-7-aarch64-linux-gnu" +- "binutils-aarch64-linux-gnu" +- "g++-arm-linux-gnueabihf" +- "g++-7-arm-linux-gnueabihf" +- "gcc-7-arm-linux-gnueabihf" +- "binutils-arm-linux-gnueabihf" +- "g++-7-multilib" +- "gcc-7-multilib" +- "binutils-gold" +- "git" +- "pkg-config" +- "faketime" +- "bsdmainutils" +- "ca-certificates" +- "python" +- "libftdi-dev" +remotes: +- "url": "https://github.com/13-37-org/infnoise" + "dir": "infnoise" +files: [] +script: | + WRAP_DIR=$HOME/wrapped + HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu" + CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" + FAKETIME_HOST_PROGS="" + FAKETIME_PROGS="date ar ranlib nm" + HOST_CFLAGS="-O2 -g" + HOST_CXXFLAGS="-O2 -g" + HOST_LDFLAGS=-static-libstdc++ + export QT_RCC_TEST=1 + export GZIP="-9n" + export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export TZ="UTC" + export BUILD_DIR=`pwd` + mkdir -p ${WRAP_DIR} + if test -n "$GBUILD_CACHE_ENABLED"; then + export SOURCES_PATH=${GBUILD_COMMON_CACHE} + export BASE_CACHE=${GBUILD_PACKAGE_CACHE} + mkdir -p ${BASE_CACHE} ${SOURCES_PATH} + fi + function create_global_faketime_wrappers { + for prog in ${FAKETIME_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} + echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${prog} + chmod +x ${WRAP_DIR}/${prog} + done + } + function create_per-host_faketime_wrappers { + for i in $HOSTS; do + for prog in ${FAKETIME_HOST_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} + echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} + chmod +x ${WRAP_DIR}/${i}-${prog} + done + done + } + # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} + EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes + mkdir -p $EXTRA_INCLUDES_BASE + # x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm, + # but we can't write there. Instead, create a link here and force it to be included in the + # search paths by wrapping gcc/g++. + mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu + rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm + ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm + for prog in gcc g++; do + rm -f ${WRAP_DIR}/${prog} + + cat << EOF > ${WRAP_DIR}/${prog} + #!/usr/bin/env bash + REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`" + for var in "\$@" + do + if [ "\$var" = "-m32" ]; then + export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + break + fi + done + \$REAL \$@ + EOF + + chmod +x ${WRAP_DIR}/${prog} + done + cd infnoise/software + + BASEPREFIX=`pwd`/depends + + # Build dependencies for each host + for i in $HOSTS; do + EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$EXTRA_INCLUDES" ]; then + export HOST_ID_SALT="$EXTRA_INCLUDES" + fi + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" + unset HOST_ID_SALT + done + + # Faketime for binaries + export PATH=${PATH_orig} + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} + + # Create the release tarball using (arbitrarily) the first host + ./autogen.sh + CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ + make dist + SOURCEDIST=`echo bitcoin-*.tar.gz` + DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` + # Correct tar file order + mkdir -p temp + pushd temp + tar xf ../$SOURCEDIST + find infnoise-* | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST + popd + # Workaround for tarball not building with the bare tag version (prep) + make -C src obj/build.h + ORIGPATH="$PATH" + + # Extract the release tarball into a dir for each host and build + for i in ${HOSTS}; do + export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} + mkdir -p distsrc-${i} + cd distsrc-${i} + INSTALLPATH=`pwd`/installed/${DISTNAME} + mkdir -p ${INSTALLPATH} + tar --strip-components=1 -xf ../$SOURCEDIST + + # Workaround for tarball not building with the bare tag version + echo '#!/bin/true' >share/genbuild.sh + mkdir src/obj + cp ../src/obj/build.h src/obj/ + + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" + make ${MAKEOPTS} + make ${MAKEOPTS} -C src check-security + + #TODO: This is a quick hack that disables symbol checking for arm. + # Instead, we should investigate why these are popping up. + # For aarch64, we'll need to bump up the min GLIBC version, as the abi + # support wasn't introduced until 2.17. + case $i in + aarch64-*) : ;; + arm-*) : ;; + *) make ${MAKEOPTS} -C src check-symbols ;; + esac + make install DESTDIR=${INSTALLPATH} + cd installed + find . -name "lib*.la" -delete + find . -name "lib*.a" -delete + rm -rf ${DISTNAME}/lib/pkgconfig + find ${DISTNAME}/bin -type f -executable -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; + find ${DISTNAME}/lib -type f -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; + find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz + find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz + cd ../../ + rm -rf distsrc-${i} + done + mkdir -p $OUTDIR/src + mv $SOURCEDIST $OUTDIR/src diff --git a/software/infnoise.c b/software/infnoise.c index 0e323cc..4ff96f3 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -225,15 +225,18 @@ int main(int argc, char **argv) { char *message = "no data?"; bool errorFlag = false; if (opts.listDevices) { + devlist_node devlist = listUSBDevices(&message); - devlist_node curdev; + if (devlist == NULL) { + fprintf(stderr, "Error: %s\n", message); + return 1; + } + devlist_node curdev = NULL; uint8_t i=0; - for (curdev = devlist; curdev != NULL;i++) { - printf("Manufacturer: %s, Description: %s, Serial: %s\n", curdev->manufacturer, curdev->description, - curdev->serial); + for (curdev = devlist; curdev != NULL; i++) { + printf("ID: %i, Manufacturer: %s, Description: %s, Serial: %s\n", curdev->id, curdev->manufacturer, curdev->description, curdev->serial); curdev = curdev->next; } - //fputs(message, stdout); // TODO: iterate through infnoise_devlist and print stuff return 0; } diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 8d9d034..43106c0 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -211,50 +211,37 @@ devlist_node listUSBDevices(char **message) { // 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?"; } else { - *message = "Can't find Infinite Noise Multiplier"; + *message = "Can't find Infinite Noise Multiplier."; } } - - devlist_node return_list =NULL; - devlist_node *current_entry =NULL; + devlist_node return_list = malloc(sizeof(struct infnoise_devlist_node)); + devlist_node current_entry = return_list; for (curdev = devlist; curdev != NULL; i++) { - if (return_list == NULL) { - return_list = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); - return_list->id = i; - return_list->serial = serial; - return_list->manufacturer = manufacturer; - return_list->description = description; - *current_entry = return_list; - } else { - (*current_entry)->next = (devlist_node) malloc(sizeof(struct infnoise_devlist_node)); - *current_entry = (*current_entry)->next; - (*current_entry)->id = i; - (*current_entry)->serial = serial; - (*current_entry)->manufacturer = manufacturer; - (*current_entry)->description = description; - } - 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?"; - return return_list; + return NULL; } //*message = "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); - return return_list; + return NULL; } + current_entry->id = i; + strcpy(current_entry->serial, serial); + strcpy(current_entry->manufacturer, manufacturer); + strcpy(current_entry->description, description); + current_entry->next = malloc(sizeof(struct infnoise_devlist_node)); + current_entry = current_entry->next; - // print to stdout - printf("debug: Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); + //printf("debug: Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); curdev = curdev->next; - //current_node = current_node->next; // ??? } + current_entry = NULL; return return_list; } diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 26d867d..19400a8 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -23,9 +23,9 @@ struct infnoise_context { struct infnoise_devlist_node { uint8_t id; - char *manufacturer; - char *description; - char *serial; + char manufacturer[128]; + char description[129]; + char serial[128]; struct infnoise_devlist_node *next; }; From 15abb6571fd71ff4d7aec8e66eb5edfc23670b03 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Thu, 26 Jul 2018 18:21:04 +0200 Subject: [PATCH 09/17] reformat code, many fixes, still some bugs (--dev-random with multiplier behaves very strange) --- software/infnoise.c | 115 ++++++++++++++++++++------------------- software/libinfnoise.c | 119 +++++++++++++++++++++-------------------- software/libinfnoise.h | 65 ++++++++++++++++------ 3 files changed, 169 insertions(+), 130 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index 4ff96f3..27ebe0c 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -8,9 +8,11 @@ #include #include #include + #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) #include #endif + #include #include #include @@ -32,28 +34,25 @@ static void initOpts(struct opt_struct *opts) { opts->help = false; opts->none = false; opts->pidFileName = - opts->serial = NULL; + 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}}; - + {"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) { @@ -95,7 +94,6 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe } int main(int argc, char **argv) { - //struct ftdi_context ftdic; struct infnoise_context context; struct opt_struct opts; int ch; @@ -105,7 +103,7 @@ 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; @@ -162,21 +160,21 @@ int main(int argc, char **argv) { 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 { @@ -191,7 +189,7 @@ int main(int argc, char **argv) { } } - if (opts.debug == false) { + if (!opts.debug) { if (getenv("INFNOISE_DEBUG") != NULL) { if (!strcmp("true", getenv("INFNOISE_DEBUG"))) { opts.debug = true; @@ -199,7 +197,7 @@ int main(int argc, char **argv) { } } - if (multiplierAssigned == false) { + if (!multiplierAssigned) { if (getenv("INFNOISE_MULTIPLIER") != NULL) { int tmpOutputMult = atoi(getenv("INFNOISE_MULTIPLIER")); if (tmpOutputMult < 0) { @@ -222,20 +220,18 @@ int main(int argc, char **argv) { return 0; } - char *message = "no data?"; - bool errorFlag = false; if (opts.listDevices) { - - devlist_node devlist = listUSBDevices(&message); + devlist_node devlist = listUSBDevices(&context.message); if (devlist == NULL) { - fprintf(stderr, "Error: %s\n", message); + fprintf(stderr, "Error: %s\n", context.message); return 1; } devlist_node curdev = NULL; - uint8_t i=0; + uint8_t i = 0; for (curdev = devlist; curdev != NULL; i++) { - printf("ID: %i, Manufacturer: %s, Description: %s, Serial: %s\n", curdev->id, curdev->manufacturer, curdev->description, curdev->serial); - curdev = curdev->next; + printf("ID: %i, Manufacturer: %s, Description: %s, Serial: %s\n", curdev->id, curdev->manufacturer, + curdev->description, curdev->serial); + curdev = curdev->next; } return 0; } @@ -255,7 +251,8 @@ int main(int argc, char **argv) { #endif #if defined(__APPLE__) message = "dev/random not supported on macOS"; - return 0; + fprintf(stderr, "Error: %s\n", context.message); + return 1; #endif } @@ -267,11 +264,12 @@ int main(int argc, char **argv) { fprintf(stderr, "Error: %s\n", context.message); return 1; // ERROR } + context.errorFlag = false; // calculate output size based on the parameters: // 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) { + uint64_t resultSize; + if (opts.outputMultiplier == 0 || opts.raw) { resultSize = BUFLEN / 8u; } else { resultSize = opts.outputMultiplier * 32u; @@ -283,24 +281,25 @@ int main(int argc, char **argv) { uint8_t result[resultSize]; uint64_t prevTotalBytesWritten = totalBytesWritten; - if (opts.raw) { - totalBytesWritten += readRawData(&context, result); - } else { - totalBytesWritten += readData(&context, result, opts.outputMultiplier); - } - - if (errorFlag) { - fprintf(stderr, "Error: %s\n", message); + totalBytesWritten += readData(&context, result, opts.raw, opts.outputMultiplier); + //fprintf(stderr, "Stats: %d\n", context.entropyThisTime); + + if (context.errorFlag) { + fprintf(stderr, "Error: %s\n", context.message); return 1; } - + if (!opts.noOutput) { - outputBytes(result, totalBytesWritten - prevTotalBytesWritten, context.entropyThisTime, opts.devRandom, &message); + if (!outputBytes(result, totalBytesWritten - prevTotalBytesWritten, context.entropyThisTime, opts.devRandom, + &context.message)) { + fprintf(stderr, "Error: %s\n", context.message); + return 1; + }; } - if (opts.debug && (1u << 20u)*(totalBytesWritten / (1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten / (1u << 20u))) { + 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/libinfnoise.c b/software/libinfnoise.c index 43106c0..e95d18a 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -52,7 +52,7 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b uint32_t warmupRounds = 0; //bool errorFlag = false; while (!inmHealthCheckOkToUseData()) { - readRawData(context, NULL); + readData(context, NULL, true, 0); warmupRounds++; } @@ -79,7 +79,6 @@ 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; @@ -112,10 +111,8 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro // 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) { + 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) { @@ -124,7 +121,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, if (raw) { // In raw mode, we just output raw data from the INM. if (result != NULL) { - memcpy(result, bytes, BUFLEN / 8u * sizeof (uint8_t)); + memcpy(result, bytes, BUFLEN / 8u * sizeof(uint8_t)); } return BUFLEN / 8u; } @@ -137,13 +134,13 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, // 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]; + uint8_t dataOut[16u * 8u]; // ??? if (outputMultiplier == 0u) { // Output all the bytes of entropy we have KeccakExtract(keccakState, dataOut, (entropy + 63u) / 64u); if (result != NULL) { - memcpy(result, dataOut, entropy / 8u * sizeof (uint8_t)); + memcpy(result, dataOut, entropy / 8u * sizeof(uint8_t)); } return entropy / 8u; } @@ -163,13 +160,14 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, if (entropyThisTime > 8u * bytesToWrite) { entropyThisTime = 8u * bytesToWrite; } - //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work? + memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); // ? // 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]; - } - } +// if (result != NULL) { +// for (uint32_t i = 0; i < bytesToWrite; i++) { +// result[bytesWritten + i] = dataOut[i]; +// } +// } + bytesWritten += bytesToWrite; numBits -= bytesToWrite * 8u; entropy -= entropyThisTime; @@ -187,7 +185,6 @@ 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; @@ -199,7 +196,6 @@ bool isSuperUser(void) { } // Return a list of all infinite noise multipliers found. - devlist_node listUSBDevices(char **message) { struct ftdi_context ftdic; ftdi_init(&ftdic); @@ -209,7 +205,7 @@ devlist_node listUSBDevices(char **message) { char manufacturer[128], description[128], serial[128]; int i = 0; - // search devices + // search devices int rc = ftdi_usb_find_all(&ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID); if (rc < 0) { if (!isSuperUser()) { @@ -246,8 +242,7 @@ devlist_node listUSBDevices(char **message) { } // Initialize the Infinite Noise Multiplier USB interface. - -bool initializeUSB(struct ftdi_context *ftdic, char **message,char *serial) { +bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { ftdi_init(ftdic); struct ftdi_device_list *devlist; @@ -327,7 +322,7 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message,char *serial) { return true; } -uint32_t readRawData(struct infnoise_context *context, uint8_t *result) { +uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier) { uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); @@ -351,49 +346,17 @@ uint32_t readRawData(struct infnoise_context *context, uint8_t *result) { uint8_t bytes[BUFLEN / 8u]; context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); - // call health check and process bytes if OK + // call health check and return bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { - return processBytes(bytes, result, context->entropyThisTime, true, 0, &context->message, &context->errorFlag); + return processBytes(bytes, result, context->entropyThisTime, raw, outputMultiplier, &context->message, + &context->errorFlag); } } return 0; } -uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier) { - uint8_t inBuf[BUFLEN]; - struct timespec start; - clock_gettime(CLOCK_REALTIME, &start); - - // write clock signal - if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) { - context->message = "USB write failed"; - context->errorFlag = true; - } - - // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { - context->message = "USB read failed"; - context->errorFlag = true; - } - - 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]; - context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); - - // call health check and process bytes if OK - if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { - return processBytes(bytes, result, context->entropyThisTime, false, outputMultiplier, &context->message, &context->errorFlag); - } - } - return 0; -} -// - -#ifdef LIB_EXAMPLE_PROGRAM -// example use of libinfnoise - with keccak +#ifdef LIB_EXAMPLE_PROGRAM_RAW +// example use of libinfnoise - raw // TODO: rewrite! int main() { @@ -432,3 +395,45 @@ int main() { } } #endif + + +#ifdef LIB_EXAMPLE_PROGRAM_WHITENED +// example use of libinfnoise - with keccak +// TODO: rewrite! + +int main() { + char *serial = NULL; // use any device, can be set to a specific serial + + // initialize USB + struct ftdi_context ftdic; + initInfnoise(&ftdic, serial); + + // parameters for readData(..): + bool rawOutput = true; + uint32_t multiplier = 10u; + + // calculate output size based on the parameters: + // when using the multiplier, we need a result array of 32*MULTIPLIER - otherwise 64(BUFLEN/8) bytes + uint32_t resultSize; + if (multiplier == 0 || rawOutput) { + resultSize = BUFLEN / 8u; + } else { + resultSize = multiplier * 32u; + } + + uint64_t totalBytesWritten = 0u; + + // read and print in a loop + while (totalBytesWritten < 100000) { + uint8_t result[resultSize]; + uint64_t bytesWritten = 0u; + bytesWritten = readData(&ftdic, keccakState, result, multiplier); + + // check for -1, indicating an error + totalBytesWritten += bytesWritten; + + // make sure to only read as many bytes as readData returned. Only those have passed the health check in this round (usually all) + fwrite(result, 1, bytesWritten, stdout); + } +} +#endif diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 19400a8..38ec589 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -1,11 +1,13 @@ #include #include #include + #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(__FreeBSD__) #include #else #include #endif + #include #include @@ -14,27 +16,60 @@ #define BUFLEN 512u struct infnoise_context { - struct ftdi_context ftdic; - uint32_t entropyThisTime; - char *message; - bool errorFlag; - //uint8_t keccakState[KeccakPermutationSizeInBytes]; + struct ftdi_context ftdic; + uint32_t entropyThisTime; + char *message; + bool errorFlag; + //uint8_t keccakState[KeccakPermutationSizeInBytes]; }; struct infnoise_devlist_node { - uint8_t id; - char manufacturer[128]; - char description[129]; - char serial[128]; - struct infnoise_devlist_node *next; + uint8_t id; + char manufacturer[128]; + char description[129]; + char serial[128]; + struct infnoise_devlist_node *next; }; -typedef struct infnoise_devlist_node* devlist_node; +typedef struct infnoise_devlist_node *devlist_node; -devlist_node listUSBDevices(char** message); +/* + * returns a struct of infnoise_devlist_node listing all connected FTDI FT240 devices by its USB descriptors, + * + * parameters: + * - message: pointer for error message + * + * returns: NULL when none found or infnoise_devlist_node + */ +devlist_node listUSBDevices(char **message); + +/* + * initialize the Infinite Noise TRNG - must be called once before readData() works. + * + * parameters: + * - context: pointer to infnoise_context struct + * - serial: optional serial number of the device (NULL) + * - keccak: initialize Keccak sponge (required to use readData with raw=false) + * - debug: debug flag + * returns: boolean success indicator (0=success) +*/ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug); -uint32_t readRawData(struct infnoise_context *context, uint8_t *result); - -uint32_t readData(struct infnoise_context *context, uint8_t *result, uint32_t outputMultiplier); +/* + * Reads some bytes from the TRNG and stores them in the "result" byte array. + * The array has to be of sufficient size. Please refer to the example programs. + * + * After each read operation, the infnoise_context's errorFlag must be checked, + * and the data from this call has to be discarded! + * Detailed error messages can be found in context->message. + * + * parameters: + * - context: infnoise_context struct with device pointer and state variables + * - result: pointer to byte array to store the result + * - raw: boolean flag for raw or whitened output + * - outputMultiplier: only used for whitened output + * + * returns: number of bytes written to the array +*/ +uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier); From 2b31329ac6d96aae6fb23d3e23949fb50c478b06 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Fri, 27 Jul 2018 09:09:29 +0200 Subject: [PATCH 10/17] fix --list-devices --- software/libinfnoise.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/software/libinfnoise.c b/software/libinfnoise.c index e95d18a..1dc0e94 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -231,13 +231,15 @@ devlist_node listUSBDevices(char **message) { strcpy(current_entry->serial, serial); strcpy(current_entry->manufacturer, manufacturer); strcpy(current_entry->description, description); - current_entry->next = malloc(sizeof(struct infnoise_devlist_node)); - current_entry = current_entry->next; - + if (curdev->next) { + current_entry->next = malloc(sizeof(struct infnoise_devlist_node)); + current_entry = current_entry->next; + } else { + current_entry->next = NULL; + } //printf("debug: Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); curdev = curdev->next; } - current_entry = NULL; return return_list; } From 2534f78730ca92e26f6cac9a1404b55177ac4e4f Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Sat, 11 Aug 2018 23:11:11 +0200 Subject: [PATCH 11/17] remove libinfnoise dependancy from binary --- software/Makefile.linux | 2 +- software/Makefile.macos | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/software/Makefile.linux b/software/Makefile.linux index 71b774c..4339ac2 100644 --- a/software/Makefile.linux +++ b/software/Makefile.linux @@ -20,7 +20,7 @@ endif all: libinfnoise.a libinfnoise.so infnoise infnoise: libinfnoise.a infnoise.o daemon.o - $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -lrt -L. -linfnoise + $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -lrt -L. %.o: %.c infnoise.h libinfnoise.h $(CC) -c -o $@ $< $(CFLAGS) diff --git a/software/Makefile.macos b/software/Makefile.macos index 1d40e7b..aa696ec 100644 --- a/software/Makefile.macos +++ b/software/Makefile.macos @@ -20,7 +20,7 @@ RM=rm all: libinfnoise.a libinfnoise.so infnoise infnoise: libinfnoise.a infnoise.o daemon.o - $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -L. -L $(FTDILOCL) -linfnoise + $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -L. -L $(FTDILOCL) %.o: %.c infnoise.h libinfnoise.h $(CC) -c -o $@ $< $(CFLAGS) From 8a930f2783cfdc4422bf9e568b1d9cee5506215e Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Sat, 11 Aug 2018 23:16:50 +0200 Subject: [PATCH 12/17] fix buffer size for multiplier mode --- software/infnoise.c | 16 +++++++----- software/libinfnoise.c | 48 +++++++++++++++++++++------------- software/libinfnoise_private.h | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index 27ebe0c..9d47697 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -86,7 +86,11 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe return false; #endif #ifdef LINUX + fputs("room?", stderr); inmWaitForPoolToHaveRoom(); + fputs("room!", stderr); + printf("length: - %ul\n", length); + printf("entropy: - %ul\n", entropy); inmWriteEntropyToPool(bytes, length, entropy); #endif } @@ -274,14 +278,14 @@ int main(int argc, char **argv) { } else { resultSize = opts.outputMultiplier * 32u; } + //fprintf(stderr, "resultsize: %lu\n", resultSize); // endless loop uint64_t totalBytesWritten = 0u; while (true) { uint8_t result[resultSize]; - uint64_t prevTotalBytesWritten = totalBytesWritten; - - totalBytesWritten += readData(&context, result, opts.raw, opts.outputMultiplier); + uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier); + totalBytesWritten += bytesWritten; //fprintf(stderr, "Stats: %d\n", context.entropyThisTime); if (context.errorFlag) { @@ -290,7 +294,7 @@ int main(int argc, char **argv) { } if (!opts.noOutput) { - if (!outputBytes(result, totalBytesWritten - prevTotalBytesWritten, context.entropyThisTime, opts.devRandom, + if (!outputBytes(result, bytesWritten, context.entropyThisTime, opts.devRandom, &context.message)) { fprintf(stderr, "Error: %s\n", context.message); return 1; @@ -298,8 +302,8 @@ int main(int argc, char **argv) { } if (opts.debug && - (1u << 20u) * (totalBytesWritten / (1u << 20u)) > (1u << 20u) * (prevTotalBytesWritten / (1u << 20u))) { + (1u << 20u) * (totalBytesWritten / (1u << 20u)) > (1u << 20u) * (totalBytesWritten + bytesWritten / (1u << 20u))) { fprintf(stderr, "Output %lu bytes\n", (unsigned long) totalBytesWritten); } } -} \ No newline at end of file +} diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 1dc0e94..68885c2 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -25,6 +25,7 @@ uint8_t keccakState[KeccakPermutationSizeInBytes]; bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug) { + context->message=""; prepareOutputBuffer(); // initialize health check @@ -45,6 +46,7 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b if (keccak) { KeccakInitialize(); KeccakInitializeState(keccakState); + //fprintf(stderr, "debug: keccak init: %s\n", context->message); } // let healthcheck collect some data @@ -97,6 +99,7 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro if (!inmHealthCheckAddBit(evenBit, oddBit, even)) { *message = "Health check of Infinite Noise Multiplier failed!"; *errorFlag = true; + fprintf(stderr, "Error: %s\n", *message); return 0; } } @@ -111,12 +114,12 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro // 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, +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) { // In raw mode, we just output raw data from the INM. @@ -134,21 +137,22 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, // 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) { + uint8_t dataOut[*entropy/8u]; // ??? // 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)); + memcpy(result, dataOut, *entropy / 8u * sizeof(uint8_t)); } - return entropy / 8u; + return *entropy / 8u; } // Output 256*outputMultipler bits. uint32_t numBits = outputMultiplier * 256u; uint32_t bytesWritten = 0u; - + uint8_t dataOut[outputMultiplier * 32u]; // ??? while (numBits > 0u) { // Write up to 1024 bits at a time. uint32_t bytesToWrite = 1024u / 8u; @@ -156,30 +160,34 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, bytesToWrite = numBits / 8u; } KeccakExtract(keccakState, dataOut, bytesToWrite / 8u); - uint32_t entropyThisTime = entropy; + uint32_t entropyThisTime = *entropy; if (entropyThisTime > 8u * bytesToWrite) { entropyThisTime = 8u * bytesToWrite; } - memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); // ? +// memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); // ? // 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]; -// } -// } + if (result != NULL) { + for (uint32_t i = 0; i < bytesToWrite; i++) { + result[bytesWritten + i] = dataOut[i]; + } + } + //fprintf(stderr, "bytesWritten: %ul\n", bytesWritten); + //fprintf(stderr, "entropy: %ul\n", *entropy); bytesWritten += bytesToWrite; numBits -= bytesToWrite * 8u; - entropy -= entropyThisTime; + *entropy -= entropyThisTime; if (numBits > 0u) { KeccakPermutation(keccakState); } } if (bytesWritten != outputMultiplier * (256u / 8u)) { *message = "Internal error outputting bytes"; + //fprintf(stderr, "ERROR: %ul", bytesWritten); *errorFlag = true; return 0; } + //fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); return bytesWritten; } @@ -339,6 +347,7 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, u if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { context->message = "USB read failed"; context->errorFlag = true; + return 0; } struct timespec end; @@ -347,10 +356,13 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, u if (us <= MAX_MICROSEC_FOR_SAMPLES) { uint8_t bytes[BUFLEN / 8u]; context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); - + if (context->errorFlag) { + //fprintf(stderr, "ERROR1: %ul\n", context->entropyThisTime); + return 0; + } // call health check and return bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { - return processBytes(bytes, result, context->entropyThisTime, raw, outputMultiplier, &context->message, + return processBytes(bytes, result, &context->entropyThisTime, raw, outputMultiplier, &context->message, &context->errorFlag); } } diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 253f773..53032f3 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -60,7 +60,7 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message); -uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy, bool raw, +uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bool raw, uint32_t outputMultiplier, char **message, bool *errorFlag); //uint32_t readData_private(struct infnoise_context *context, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom); From 9f241bcd274a365cc336a6467e6d96a4085da9df Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Sat, 11 Aug 2018 23:29:34 +0200 Subject: [PATCH 13/17] remove debug messages --- software/infnoise.c | 8 ++++---- software/libinfnoise.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index 9d47697..3ab3904 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -86,11 +86,11 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe return false; #endif #ifdef LINUX - fputs("room?", stderr); + //fputs("room?", stderr); inmWaitForPoolToHaveRoom(); - fputs("room!", stderr); - printf("length: - %ul\n", length); - printf("entropy: - %ul\n", entropy); + //fputs("room!", stderr); + //printf("length: - %ul\n", length); + //printf("entropy: - %ul\n", entropy); inmWriteEntropyToPool(bytes, length, entropy); #endif } diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 68885c2..3e96bd3 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -139,7 +139,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, KeccakAbsorb(keccakState, bytes, BUFLEN / 64u); if (outputMultiplier == 0u) { - uint8_t dataOut[*entropy/8u]; // ??? + uint8_t dataOut[16u*8u]; // ??? // Output all the bytes of entropy we have KeccakExtract(keccakState, dataOut, (*entropy + 63u) / 64u); @@ -153,6 +153,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, uint32_t numBits = outputMultiplier * 256u; uint32_t bytesWritten = 0u; uint8_t dataOut[outputMultiplier * 32u]; // ??? + while (numBits > 0u) { // Write up to 1024 bits at a time. uint32_t bytesToWrite = 1024u / 8u; From 25605e673eb66c2ed19ce6d254baa7bf94725845 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Wed, 15 Aug 2018 17:21:59 +0200 Subject: [PATCH 14/17] fix --dev-random mode (multipliers still buggy) --- software/infnoise.c | 10 ++++++---- software/libinfnoise.c | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/software/infnoise.c b/software/infnoise.c index 3ab3904..93a2879 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -88,9 +88,10 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe #ifdef LINUX //fputs("room?", stderr); inmWaitForPoolToHaveRoom(); - //fputs("room!", stderr); - //printf("length: - %ul\n", length); - //printf("entropy: - %ul\n", entropy); + fputs("room!", stderr); + printf("length: - %ul\n", length); + printf("entropy: - %ul\n", entropy); + //fwrite(bytes, 1, length, stdout); inmWriteEntropyToPool(bytes, length, entropy); #endif } @@ -286,7 +287,7 @@ int main(int argc, char **argv) { uint8_t result[resultSize]; uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier); totalBytesWritten += bytesWritten; - //fprintf(stderr, "Stats: %d\n", context.entropyThisTime); + fprintf(stderr, "Stats: %d\n", context.entropyThisTime); if (context.errorFlag) { fprintf(stderr, "Error: %s\n", context.message); @@ -294,6 +295,7 @@ int main(int argc, char **argv) { } if (!opts.noOutput) { + fprintf(stderr, "E: %ul\n", context.entropyThisTime); if (!outputBytes(result, bytesWritten, context.entropyThisTime, opts.devRandom, &context.message)) { fprintf(stderr, "Error: %s\n", context.message); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 3e96bd3..0001c34 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -177,7 +177,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bytesWritten += bytesToWrite; numBits -= bytesToWrite * 8u; - *entropy -= entropyThisTime; + //*entropy -= entropyThisTime; if (numBits > 0u) { KeccakPermutation(keccakState); } @@ -188,7 +188,7 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, *errorFlag = true; return 0; } - //fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); + fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); return bytesWritten; } From 71df49d7bf88a7341f7527bad70a532a52d3db8f Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Mon, 27 Aug 2018 17:48:27 +0200 Subject: [PATCH 15/17] next big step completed: fixed keccak multiplicator and --dev-random mode after libinfnoise refactoring (interface changed!) --- software/Makefile.freebsd | 2 +- software/infnoise.c | 8 +- software/libinfnoise.c | 141 +++++++++++++++++---------------- software/libinfnoise.h | 4 + software/libinfnoise_private.h | 4 +- 5 files changed, 85 insertions(+), 74 deletions(-) diff --git a/software/Makefile.freebsd b/software/Makefile.freebsd index c7b42fd..6be34e2 100644 --- a/software/Makefile.freebsd +++ b/software/Makefile.freebsd @@ -20,7 +20,7 @@ RM=rm all: libinfnoise.a libinfnoise.so infnoise infnoise: libinfnoise.a infnoise.o daemon.o - $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -L. -L $(FTDILOCL) + $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -L. -L $(FTDILOCL) %.o: %.c infnoise.h libinfnoise.h $(CC) -c -o $@ $< $(CFLAGS) diff --git a/software/infnoise.c b/software/infnoise.c index 93a2879..0df5df8 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -286,16 +286,18 @@ int main(int argc, char **argv) { while (true) { uint8_t result[resultSize]; uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier); - totalBytesWritten += bytesWritten; - fprintf(stderr, "Stats: %d\n", context.entropyThisTime); + totalBytesWritten += bytesWritten; +// fprintf(stderr, "Stats: %d\n", context.entropyThisTime); if (context.errorFlag) { fprintf(stderr, "Error: %s\n", context.message); return 1; } + //fprintf(stderr, "Error: %s\n", context.message); if (!opts.noOutput) { - fprintf(stderr, "E: %ul\n", context.entropyThisTime); + //fprintf(stderr, "B: %lu\n", bytesWritten); + //fprintf(stderr, "E: %ul\n", context.entropyThisTime); if (!outputBytes(result, bytesWritten, context.entropyThisTime, opts.devRandom, &context.message)) { fprintf(stderr, "Error: %s\n", context.message); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 0001c34..a8f28a1 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -50,7 +50,7 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b } // let healthcheck collect some data - uint32_t maxWarmupRounds = 500; + uint32_t maxWarmupRounds = 5000; uint32_t warmupRounds = 0; //bool errorFlag = false; while (!inmHealthCheckOkToUseData()) { @@ -99,7 +99,7 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro if (!inmHealthCheckAddBit(evenBit, oddBit, even)) { *message = "Health check of Infinite Noise Multiplier failed!"; *errorFlag = true; - fprintf(stderr, "Error: %s\n", *message); + fprintf(stderr, "health-Error: %s\n", *message); return 0; } } @@ -115,7 +115,8 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro // 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) { + uint32_t *numBits, uint32_t *bytesWritten, + bool raw, uint32_t outputMultiplier) { //Use the lower of the measured entropy and the provable lower bound on //average entropy. if (*entropy > inmExpectedEntropyPerBit * BUFLEN / INM_ACCURACY) { @@ -136,63 +137,47 @@ 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". + + uint8_t dataOut[1024u]; KeccakAbsorb(keccakState, bytes, BUFLEN / 64u); if (outputMultiplier == 0u) { - uint8_t dataOut[16u*8u]; // ??? // Output all the bytes of entropy we have KeccakExtract(keccakState, dataOut, (*entropy + 63u) / 64u); - 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; - uint8_t dataOut[outputMultiplier * 32u]; // ??? + // Output 256*outputMultipler bits (in chunks of 1024) + // only the first 1024 now, + if (*numBits == 0u) { + *numBits = outputMultiplier*256u; + *bytesWritten = 0u; - while (numBits > 0u) { - // Write up to 1024 bits at a time. + // Output up to 1024 bits at a time. uint32_t bytesToWrite = 1024u / 8u; - if (bytesToWrite > numBits / 8u) { - bytesToWrite = numBits / 8u; + if (bytesToWrite > *numBits / 8u) { + bytesToWrite = *numBits / 8u; } - KeccakExtract(keccakState, dataOut, bytesToWrite / 8u); - uint32_t entropyThisTime = *entropy; - if (entropyThisTime > 8u * bytesToWrite) { - entropyThisTime = 8u * bytesToWrite; - } -// memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); // ? - // 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]; - } - } - //fprintf(stderr, "bytesWritten: %ul\n", bytesWritten); - //fprintf(stderr, "entropy: %ul\n", *entropy); - bytesWritten += bytesToWrite; - numBits -= bytesToWrite * 8u; - //*entropy -= entropyThisTime; - if (numBits > 0u) { - KeccakPermutation(keccakState); - } + //uint32_t entropyThisTime = *entropy; + + //if (entropyThisTime > 8u * bytesToWrite) { + // entropyThisTime = 8u * bytesToWrite; + //} + + KeccakExtract(keccakState, result, bytesToWrite / 8u); + KeccakPermutation(keccakState); + *bytesWritten = bytesToWrite; + *numBits -= bytesToWrite * 8u; } - if (bytesWritten != outputMultiplier * (256u / 8u)) { - *message = "Internal error outputting bytes"; - //fprintf(stderr, "ERROR: %ul", bytesWritten); - *errorFlag = true; - return 0; - } - fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); - return bytesWritten; + + //fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); + return *bytesWritten; } - // 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; @@ -334,37 +319,57 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) { } uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier) { - uint8_t inBuf[BUFLEN]; - struct timespec start; - clock_gettime(CLOCK_REALTIME, &start); + // check if data can be squeezed from the keccak spongr from previous state (or we need to collect some new entropy to get numBits >0) + if (context->numBits > 0u) { + // squeeze the sponge! - // write clock signal - if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) { - context->message = "USB write failed"; - context->errorFlag = true; - } + // Output up to 1024 bits at a time. + uint32_t bytesToWrite = 1024u / 8u; - // and read 512 byte from the internal buffer (in synchronous bitbang mode) - if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { - context->message = "USB read failed"; - context->errorFlag = true; - return 0; - } + if (bytesToWrite > context->numBits / 8u) { + bytesToWrite = context->numBits / 8u; + } - 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]; - context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); - if (context->errorFlag) { - //fprintf(stderr, "ERROR1: %ul\n", context->entropyThisTime); + KeccakExtract(keccakState, result, bytesToWrite / 8u); + KeccakPermutation(keccakState); + + context->bytesWritten += bytesToWrite; + context->numBits -= bytesToWrite * 8u; + return 1024/8u; + } else { // collect new entropy + uint8_t inBuf[BUFLEN]; + struct timespec start; + clock_gettime(CLOCK_REALTIME, &start); + + // write clock signal + if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) { + context->message = "USB write failed"; + context->errorFlag = true; + } + + // and read 512 byte from the internal buffer (in synchronous bitbang mode) + if (ftdi_read_data(&context->ftdic, inBuf, BUFLEN) != BUFLEN) { + context->message = "USB read failed"; + context->errorFlag = true; return 0; } - // call health check and return bytes if OK - if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { - return processBytes(bytes, result, &context->entropyThisTime, raw, outputMultiplier, &context->message, - &context->errorFlag); + + 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]; + context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); + if (context->errorFlag) { + fprintf(stderr, "ERROR1: %ul\n", context->entropyThisTime); + return 0; + } + // call health check and return bytes if OK + if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { + return processBytes(bytes, result, &context->entropyThisTime, &context->numBits, &context->bytesWritten, + raw, outputMultiplier); + } } } return 0; diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 38ec589..cf0100e 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -21,6 +21,10 @@ struct infnoise_context { char *message; bool errorFlag; //uint8_t keccakState[KeccakPermutationSizeInBytes]; + + // used in multiplier mode to keep track of bytes to be put out + uint32_t numBits; + uint32_t bytesWritten; }; struct infnoise_devlist_node { diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 53032f3..552cdf7 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -60,7 +60,7 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message); -uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bool raw, - uint32_t outputMultiplier, char **message, bool *errorFlag); +uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, uint32_t *numBits, uint32_t *bytesWritten, bool raw, + uint32_t outputMultiplier); //uint32_t readData_private(struct infnoise_context *context, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom); From 037a20d63c4f2a3fea12980422a2cb025e5a1c8b Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Mon, 3 Sep 2018 08:14:41 +0200 Subject: [PATCH 16/17] fix formatting of usage output --- software/README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/software/README.md b/software/README.md index e89f5b3..da46449 100644 --- a/software/README.md +++ b/software/README.md @@ -76,19 +76,19 @@ with the stable release for now. Usage ----- -Usage: infnoise [options] -Options are: - --debug - turn on some debug output - --dev-random - write entropy to /dev/random instead of stdout - --raw - do not whiten the output - --multiplier - write 256 bits * value for each 512 bits written to the Keccak sponge - --no-output - do not write random output data - --daemon - run in the background. Output should be redirected to a file or - the options should be used with --dev-random. To reduce CPU-usage addition - af entropy is only forced after a minute rather than a second. - --pidfile - write the process ID to a file. If --daemon is used, it is the ID of the background process. - --serial - use Infinite Noise TRNG/FT240 with the given serial number (see --list-devices) - --list-devices - list available devices + Usage: infnoise [options] + Options are: + --debug - turn on some debug output + --dev-random - write entropy to /dev/random instead of stdout + --raw - do not whiten the output + --multiplier - write 256 bits * value for each 512 bits written to the Keccak sponge + --no-output - do not write random output data + --daemon - run in the background. Output should be redirected to a file or + the options should be used with --dev-random. To reduce CPU-usage addition + af entropy is only forced after a minute rather than a second. + --pidfile - write the process ID to a file. If --daemon is used, it is the ID of the background process. + --serial - use Infinite Noise TRNG/FT240 with the given serial number (see --list-devices) + --list-devices - list available devices Note: The options --daemon and --pidfile are only implemented in the Linux version. From 9b9822bab74f8cb52241245df6a6c324d4e02d53 Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Mon, 3 Sep 2018 17:57:17 +0200 Subject: [PATCH 17/17] cleanup --- software/examples/libinfnoise/Makefile | 7 +- .../{example.c => example-complex.c} | 39 +++---- software/examples/libinfnoise/example-raw.c | 46 -------- .../examples/libinfnoise/example-simple.c | 58 ++++++++++ software/infnoise.c | 9 -- software/libinfnoise.c | 102 +----------------- 6 files changed, 88 insertions(+), 173 deletions(-) rename software/examples/libinfnoise/{example.c => example-complex.c} (51%) delete mode 100644 software/examples/libinfnoise/example-raw.c create mode 100644 software/examples/libinfnoise/example-simple.c diff --git a/software/examples/libinfnoise/Makefile b/software/examples/libinfnoise/Makefile index 1401560..68f3fd6 100644 --- a/software/examples/libinfnoise/Makefile +++ b/software/examples/libinfnoise/Makefile @@ -13,12 +13,15 @@ LDFLAGS= -shared FTDI := $(shell libftdi-config --libs) -all: libinfnoise-example libinfnoise-example-raw +all: libinfnoise-example libinfnoise-example-raw libinfnoise-example-1 libinfnoise-example: example.c $(CC) $(CFLAGS) -o libinfnoise-example example.c $(FTDI) -lm -lrt -linfnoise -libinfnoise-example-raw: example.c +libinfnoise-example-simple: example-simple.c + $(CC) $(CFLAGS) -o libinfnoise-example-1 example1.c $(FTDI) -lm -lrt -linfnoise + +libinfnoise-example-complex: example-complex.c $(CC) $(CFLAGS) -o libinfnoise-example-raw example-raw.c $(FTDI) -lm -lrt -linfnoise clean: diff --git a/software/examples/libinfnoise/example.c b/software/examples/libinfnoise/example-complex.c similarity index 51% rename from software/examples/libinfnoise/example.c rename to software/examples/libinfnoise/example-complex.c index 0344d39..9bf8033 100644 --- a/software/examples/libinfnoise/example.c +++ b/software/examples/libinfnoise/example-complex.c @@ -10,27 +10,26 @@ int main() { // parameters char *serial=NULL; // can be set to a specific serial, NULL uses the first found device - bool initKeccak = true; // initialize Keccak sponge (used for whitening) - uint32_t multiplier = 10u; // multiplier for whitening - bool debug = false; // debug mode (health monitor writes to stderr) - - char *message; - bool errorFlag = false; + bool initKeccak = false; // initialize Keccak sponge (used for whitening) + uint32_t multiplier = 1u; // multiplier for whitening + bool debug = true; // debug mode (health monitor writes to stderr) // initialize hardware and health monitor - struct ftdi_context ftdic; - if (!initInfnoise(&ftdic, serial, &message, true, debug)) { - fputs(message, stderr); + struct infnoise_context context; + fprintf(stdout, "pre-initi: %s\n", ""); + + if (!initInfnoise(&context, serial, initKeccak, debug)) { + fprintf(stdout, "erri: %s\n", ""); + fputs(context.message, stderr); return 1; // ERROR } + fprintf(stdout, "initi: %s\n", ""); - // calculate output size based on the parameters: - // when using the multiplier, we need a result array of 32*MULTIPLIER - otherwise 64(BUFLEN/8) bytes uint32_t resultSize; if (multiplier == 0 || initKeccak == false) { - resultSize = BUFLEN/8u; + resultSize = 512u; } else { - resultSize = multiplier*32u; + resultSize = 1024u; } // read and print in a loop (until 1M is read) @@ -39,18 +38,20 @@ int main() uint8_t result[resultSize]; // readRawData returns the number of bytes written to result array - uint64_t bytesWritten = readData(&ftdic, result, &message, &errorFlag, multiplier); - totalBytesWritten += bytesWritten; + uint64_t bytesWritten = readData(&context, result, !initKeccak, multiplier); + fprintf(stderr, "infnoise bytes read: %lu\n", bytesWritten); // check for errors // note: bytesWritten is also 0 in this case, but an errorFlag is needed as // bytesWritten can also be 0 when data hasn't passed the health monitor. - if (errorFlag) { - fprintf(stderr, "Error: %s\n", message); - return 1; + if (context.errorFlag) { + fprintf(stderr, "Error: %s\n", context.message); + return -1; } + fprintf(stderr, "infnoise bytes read: %lu\n", (unsigned long) bytesWritten); + totalBytesWritten += bytesWritten; - // print as many bytes + // print as many bytes as readData told us fwrite(result, 1, bytesWritten, stdout); } return 0; diff --git a/software/examples/libinfnoise/example-raw.c b/software/examples/libinfnoise/example-raw.c deleted file mode 100644 index 53d84d3..0000000 --- a/software/examples/libinfnoise/example-raw.c +++ /dev/null @@ -1,46 +0,0 @@ -/* -This is a very simple example to use libinfnoise in raw output mode. -*/ - -#include -#include -#include - -int main() -{ - // parameters - char *serial=NULL; // can be set to a specific serial, NULL uses the first found device - bool debug=true; // debug mode (health monitor writes to stderr) - - char *message; - bool errorFlag = false; - - // initialize hardware and health monitor - struct ftdi_context ftdic; - if (!initInfnoise(&ftdic, serial, &message, false, debug)) { - fputs(message, stderr); - return 1; // ERROR - } - - // read and print in a loop (until 1M) - uint32_t totalBytesWritten = 0; - while (totalBytesWritten < 1000000) { - uint8_t result[64];// result is always 64 bytes in raw mode - - // read data returns the number of bytes written to result array - uint64_t bytesWritten = readRawData(&ftdic, result, &message, &errorFlag); - totalBytesWritten += bytesWritten; - - // check for errors - // note: bytesWritten is also 0 in this case, but an errorFlag is needed as - // bytesWritten can also be 0 when data hasn't passed the health monitor. - if (errorFlag) { - fprintf(stderr, "Error: %s\n", message); - return 1; - } - - // print bytes to stdout - fwrite(result, 1, bytesWritten, stdout); - } - return 0; -} diff --git a/software/examples/libinfnoise/example-simple.c b/software/examples/libinfnoise/example-simple.c new file mode 100644 index 0000000..9bf8033 --- /dev/null +++ b/software/examples/libinfnoise/example-simple.c @@ -0,0 +1,58 @@ +/* +This is a simple example to use libinfnoise with whitened and multiplied output. +*/ + +#include +#include +#include + +int main() +{ + // parameters + char *serial=NULL; // can be set to a specific serial, NULL uses the first found device + bool initKeccak = false; // initialize Keccak sponge (used for whitening) + uint32_t multiplier = 1u; // multiplier for whitening + bool debug = true; // debug mode (health monitor writes to stderr) + + // initialize hardware and health monitor + struct infnoise_context context; + fprintf(stdout, "pre-initi: %s\n", ""); + + if (!initInfnoise(&context, serial, initKeccak, debug)) { + fprintf(stdout, "erri: %s\n", ""); + fputs(context.message, stderr); + return 1; // ERROR + } + fprintf(stdout, "initi: %s\n", ""); + + uint32_t resultSize; + if (multiplier == 0 || initKeccak == false) { + resultSize = 512u; + } else { + resultSize = 1024u; + } + + // read and print in a loop (until 1M is read) + uint64_t totalBytesWritten = 0u; + while (totalBytesWritten < 1000000) { + uint8_t result[resultSize]; + + // readRawData returns the number of bytes written to result array + uint64_t bytesWritten = readData(&context, result, !initKeccak, multiplier); + fprintf(stderr, "infnoise bytes read: %lu\n", bytesWritten); + + // check for errors + // note: bytesWritten is also 0 in this case, but an errorFlag is needed as + // bytesWritten can also be 0 when data hasn't passed the health monitor. + if (context.errorFlag) { + fprintf(stderr, "Error: %s\n", context.message); + return -1; + } + fprintf(stderr, "infnoise bytes read: %lu\n", (unsigned long) bytesWritten); + totalBytesWritten += bytesWritten; + + // print as many bytes as readData told us + fwrite(result, 1, bytesWritten, stdout); + } + return 0; +} diff --git a/software/infnoise.c b/software/infnoise.c index 0df5df8..946cce2 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -86,12 +86,7 @@ bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDe return false; #endif #ifdef LINUX - //fputs("room?", stderr); inmWaitForPoolToHaveRoom(); - fputs("room!", stderr); - printf("length: - %ul\n", length); - printf("entropy: - %ul\n", entropy); - //fwrite(bytes, 1, length, stdout); inmWriteEntropyToPool(bytes, length, entropy); #endif } @@ -287,17 +282,13 @@ int main(int argc, char **argv) { uint8_t result[resultSize]; uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier); totalBytesWritten += bytesWritten; -// fprintf(stderr, "Stats: %d\n", context.entropyThisTime); if (context.errorFlag) { fprintf(stderr, "Error: %s\n", context.message); return 1; } - //fprintf(stderr, "Error: %s\n", context.message); if (!opts.noOutput) { - //fprintf(stderr, "B: %lu\n", bytesWritten); - //fprintf(stderr, "E: %ul\n", context.entropyThisTime); if (!outputBytes(result, bytesWritten, context.entropyThisTime, opts.devRandom, &context.message)) { fprintf(stderr, "Error: %s\n", context.message); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index a8f28a1..9256cd8 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -46,7 +46,6 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b if (keccak) { KeccakInitialize(); KeccakInitializeState(keccakState); - //fprintf(stderr, "debug: keccak init: %s\n", context->message); } // let healthcheck collect some data @@ -99,7 +98,6 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro if (!inmHealthCheckAddBit(evenBit, oddBit, even)) { *message = "Health check of Infinite Noise Multiplier failed!"; *errorFlag = true; - fprintf(stderr, "health-Error: %s\n", *message); return 0; } } @@ -162,19 +160,12 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bytesToWrite = *numBits / 8u; } - //uint32_t entropyThisTime = *entropy; - - //if (entropyThisTime > 8u * bytesToWrite) { - // entropyThisTime = 8u * bytesToWrite; - //} - KeccakExtract(keccakState, result, bytesToWrite / 8u); KeccakPermutation(keccakState); *bytesWritten = bytesToWrite; *numBits -= bytesToWrite * 8u; } - - //fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten); + return *bytesWritten; } @@ -217,9 +208,10 @@ devlist_node listUSBDevices(char **message) { if (!isSuperUser()) { *message = "Can't find Infinite Noise Multiplier. Try running as super user?"; return NULL; + } else { + *message = "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); + return NULL; } - //*message = "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic)); - return NULL; } current_entry->id = i; strcpy(current_entry->serial, serial); @@ -231,7 +223,6 @@ devlist_node listUSBDevices(char **message) { } else { current_entry->next = NULL; } - //printf("debug: Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial); curdev = curdev->next; } return return_list; @@ -362,7 +353,7 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, u uint8_t bytes[BUFLEN / 8u]; context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag); if (context->errorFlag) { - fprintf(stderr, "ERROR1: %ul\n", context->entropyThisTime); + // todo: message? return 0; } // call health check and return bytes if OK @@ -374,86 +365,3 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, u } return 0; } - -#ifdef LIB_EXAMPLE_PROGRAM_RAW -// example use of libinfnoise - raw -// TODO: rewrite! - -int main() { - char *serial = NULL; // use any device, can be set to a specific serial - - // initialize USB - struct ftdi_context ftdic; - initInfnoise(&ftdic, serial); - - // parameters for readData(..): - bool rawOutput = true; - uint32_t multiplier = 10u; - - // calculate output size based on the parameters: - // 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; - } else { - resultSize = multiplier * 32u; - } - - uint64_t totalBytesWritten = 0u; - - // read and print in a loop - while (totalBytesWritten < 100000) { - uint8_t result[resultSize]; - uint64_t bytesWritten = 0u; - bytesWritten = readData(&ftdic, keccakState, result, multiplier); - - // check for -1, indicating an error - totalBytesWritten += bytesWritten; - - // make sure to only read as many bytes as readData returned. Only those have passed the health check in this round (usually all) - fwrite(result, 1, bytesWritten, stdout); - } -} -#endif - - -#ifdef LIB_EXAMPLE_PROGRAM_WHITENED -// example use of libinfnoise - with keccak -// TODO: rewrite! - -int main() { - char *serial = NULL; // use any device, can be set to a specific serial - - // initialize USB - struct ftdi_context ftdic; - initInfnoise(&ftdic, serial); - - // parameters for readData(..): - bool rawOutput = true; - uint32_t multiplier = 10u; - - // calculate output size based on the parameters: - // when using the multiplier, we need a result array of 32*MULTIPLIER - otherwise 64(BUFLEN/8) bytes - uint32_t resultSize; - if (multiplier == 0 || rawOutput) { - resultSize = BUFLEN / 8u; - } else { - resultSize = multiplier * 32u; - } - - uint64_t totalBytesWritten = 0u; - - // read and print in a loop - while (totalBytesWritten < 100000) { - uint8_t result[resultSize]; - uint64_t bytesWritten = 0u; - bytesWritten = readData(&ftdic, keccakState, result, multiplier); - - // check for -1, indicating an error - totalBytesWritten += bytesWritten; - - // make sure to only read as many bytes as readData returned. Only those have passed the health check in this round (usually all) - fwrite(result, 1, bytesWritten, stdout); - } -} -#endif