diff --git a/software/Makefile.linux b/software/Makefile.linux index db48aa5..c246dcc 100644 --- a/software/Makefile.linux +++ b/software/Makefile.linux @@ -4,7 +4,7 @@ GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --forma PREFIX = $(DESTDIR)/usr/local -CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I Keccak -I /usr/include/libftdi1 \ +CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I BLAKE3 -I /usr/include/libftdi1 \ -DGIT_VERSION=\"$(GIT_VERSION)\"\ -DGIT_COMMIT=\"$(GIT_COMMIT)\"\ -DGIT_DATE=\"$(GIT_DATE)\"\ @@ -15,25 +15,22 @@ FTDI = $(shell $(CC) -o /dev/null -x c /dev/null -shared -lftdi 2>/dev/null && e 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. + $(CC) $(CFLAGS) -o infnoise infnoise.o daemon.o libinfnoise.a $(FTDI) -lm -lrt -L. -LBLAKE3 -lblake3 %.o: %.c infnoise.h libinfnoise.h $(CC) -c -o $@ $< $(CFLAGS) -KeccakF-1600-reference.o: Keccak/KeccakF-1600-reference.c Keccak/KeccakF-1600-interface.h Keccak/brg_endian.h - $(CC) -c -o $@ $< $(CFLAGS) - # static lib compiled into infnoise binary libinfnoise.o: libinfnoise.c libinfnoise.h libinfnoise_private.h healthcheck.c $(CC) $(CFLAGS) -c libinfnoise.c -libinfnoise.a: libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o - ar rcs libinfnoise.a libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o +libinfnoise.a: libinfnoise.o healthcheck.o BLAKE3/blake3.o writeentropy.o + ar rcs libinfnoise.a libinfnoise.o healthcheck.o BLAKE3/blake3.o writeentropy.o ranlib libinfnoise.a # shared lib -libinfnoise.so: libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o - $(CC) $(CFLAGS) -fvisibility=hidden -o libinfnoise.so libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o -Wl,--version-script=libinfnoise.version $(FTDI) -lm -shared +libinfnoise.so: libinfnoise.o healthcheck.o BLAKE3/blake3.o writeentropy.o + $(CC) $(CFLAGS) -fvisibility=hidden -o libinfnoise.so libinfnoise.o healthcheck.o BLAKE3/blake3.o writeentropy.o -Wl,--version-script=libinfnoise.version $(FTDI) -lm -shared libs: libinfnoise.a diff --git a/software/infnoise.c b/software/infnoise.c index 0361b6a..a0f85a6 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -30,7 +30,6 @@ void term(int signum) } static void initOpts(struct opt_struct *opts) { - opts->outputMultiplier = 0u; opts->daemon = false; opts->debug = false; opts->devRandom = false; @@ -50,7 +49,6 @@ static struct option longopts[] = { {"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'}, @@ -104,7 +102,6 @@ int main(int argc, char **argv) { struct infnoise_context context; struct opt_struct opts; int ch; - bool multiplierAssigned = false; initOpts(&opts); @@ -124,15 +121,6 @@ int main(int argc, char **argv) { 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 || opts.pidFileName[0] == '\0') { @@ -172,8 +160,6 @@ int main(int argc, char **argv) { " -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" @@ -203,23 +189,6 @@ int main(int argc, char **argv) { && !strcmp("true", envDbg)); } - if (!multiplierAssigned) { - char *envMultiplier = getenv("INFNOISE_MULTIPLIER"); - if (envMultiplier != NULL) { - int tmpOutputMult = atoi(envMultiplier); - if (tmpOutputMult < 0) { - fputs("Multiplier must be >= 0\n", stderr); - return 1; - } - multiplierAssigned = true; - opts.outputMultiplier = tmpOutputMult; - } - } - - if (!multiplierAssigned && opts.devRandom) { - opts.outputMultiplier = 2u; // Don't throw away entropy when writing to /dev/random unless told to do so - } - if (opts.listDevices) { infnoise_devlist_node_t* devlist = listUSBDevices(&context.message); if (devlist == NULL) { @@ -263,21 +232,12 @@ 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) + // initialize USB device, health check and BLAKE3 (see libinfnoise) if (!initInfnoise(&context, opts.serial, !opts.raw, opts.debug)) { fprintf(stderr, "Error: %s\n", context.message); return 1; // ERROR } - // calculate output size based on the parameters: - uint64_t resultSize; - if (opts.outputMultiplier <= 2 || opts.raw) { - resultSize = 64u; - } else { - resultSize = 128u; - } - //fprintf(stderr, "resultsize: %lu\n", resultSize); - // get proper shutdown struct sigaction action; memset(&action, 0, sizeof(action)); @@ -288,8 +248,8 @@ int main(int argc, char **argv) { // endless loop uint64_t totalBytesWritten = 0u; while (running) { - uint8_t result[resultSize]; - uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier); + uint8_t result[64u]; + uint64_t bytesWritten = readData(&context, result, opts.raw); totalBytesWritten += bytesWritten; if (context.errorFlag) { diff --git a/software/infnoise.h b/software/infnoise.h index 3f894de..7ba96a1 100644 --- a/software/infnoise.h +++ b/software/infnoise.h @@ -9,7 +9,6 @@ // Structure for parsed command line options struct opt_struct { - uint32_t outputMultiplier; // We output all the entropy when outputMultiplier == 0 bool daemon; // Run as daemon? bool debug; // Print debugging info? bool devRandom; // Feed /dev/random? diff --git a/software/libinfnoise.c b/software/libinfnoise.c index 7c7f9f5..14744a5 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -16,20 +16,18 @@ #include #include #include "libinfnoise_private.h" -#include "KeccakF-1600-interface.h" +#include "blake3.h" #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) #include #endif -uint8_t keccakState[KeccakPermutationSizeInBytes]; +blake3_hasher blake3hasher; -bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, bool debug) { +bool initInfnoise(struct infnoise_context *context, char *serial, bool blake3, bool debug) { context->message=""; context->entropyThisTime=0; context->errorFlag=false; - context->bytesGiven=0; - context->bytesWritten=0; prepareOutputBuffer(); @@ -47,11 +45,9 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b } } - // initialize keccak - if (keccak) { - KeccakInitialize(); - KeccakInitializeState(keccakState); - } + // initialize blake3 + if (blake3) + blake3_hasher_init(&blake3hasher); // let healthcheck collect some data uint32_t maxWarmupRounds = 5000; @@ -59,7 +55,7 @@ bool initInfnoise(struct infnoise_context *context, char *serial, bool keccak, b //bool errorFlag = false; while (!inmHealthCheckOkToUseData()) { - readData(context, NULL, true, 1); + readData(context, NULL, true); warmupRounds++; } @@ -120,15 +116,9 @@ uint32_t extractBytes(uint8_t *bytes, uint32_t length, uint8_t *inBuf, const cha 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, - uint32_t *bytesGiven, uint32_t *bytesWritten, - bool raw, uint32_t outputMultiplier) { +// Whiten the output, if requested. Output bytes only if the health +// checker says it's OK. +uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bool raw) { //Use the lower of the measured entropy and the provable lower bound on //average entropy. if (*entropy > inmExpectedEntropyPerBit * BUFLEN / INM_ACCURACY) { @@ -142,50 +132,11 @@ uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, 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". - uint8_t resultSize; - if (outputMultiplier <= 2) { - resultSize = 64u; - } else { - resultSize = 128u; - } - - uint8_t dataOut[resultSize]; - KeccakAbsorb(keccakState, bytes, BUFLEN / 64u); - - 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)); - } - return *entropy / 8u; + blake3_hasher_update(&blake3hasher, bytes, *entropy / 8u * sizeof(uint8_t)); + if (result != NULL) { + blake3_hasher_finalize(&blake3hasher, result, *entropy / 8u * sizeof(uint8_t)); } - - // Output 256*outputMultipler bits (in chunks of 1024) - // only the first 1024 now, - if (*bytesGiven == 0u) { - *bytesGiven = outputMultiplier*256u / 8u; - *bytesWritten = 0u; - - // Output up to 1024 bits at a time. - uint32_t bytesToWrite = 1024u / 8u; - if (bytesToWrite > *bytesGiven) { - bytesToWrite = *bytesGiven; - } - - KeccakExtract(keccakState, result, bytesToWrite / 8u); - KeccakPermutation(keccakState); - *bytesWritten = bytesToWrite; - *bytesGiven -= bytesToWrite; - } - return *bytesWritten; + return *entropy / 8u; } // Return the difference in the times as a double in microseconds. @@ -351,25 +302,7 @@ bool initializeUSB(struct ftdi_context *ftdic, const char **message, char *seria return true; } -uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier) { - // check if data can be squeezed from the keccak sponge from previous state (or we need to collect some new entropy to get bytesGiven >0) - if (context->bytesGiven > 0u) { - // squeeze the sponge! - - // Output up to 1024 bits at a time. - uint32_t bytesToWrite = 1024u / 8u; - - if (bytesToWrite > context->bytesGiven) { - bytesToWrite = context->bytesGiven; - } - - KeccakExtract(keccakState, result, bytesToWrite / 8u); - KeccakPermutation(keccakState); - - context->bytesWritten += bytesToWrite; - context->bytesGiven -= bytesToWrite; - return bytesToWrite; - } else { // collect new entropy +uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw) { uint8_t inBuf[BUFLEN]; struct timespec start; clock_gettime(CLOCK_REALTIME, &start); @@ -400,10 +333,9 @@ uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, u } // call health check and return bytes if OK if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(context->entropyThisTime, BUFLEN)) { - return processBytes(bytes, result, &context->entropyThisTime, &context->bytesGiven, &context->bytesWritten, - raw, outputMultiplier); + return processBytes(bytes, result, &context->entropyThisTime, raw); } } - } + return 0; } diff --git a/software/libinfnoise.h b/software/libinfnoise.h index 4c0b75b..a21c9e0 100644 --- a/software/libinfnoise.h +++ b/software/libinfnoise.h @@ -12,7 +12,6 @@ #include // The FT240X has a 512 byte buffer. Must be multiple of 64 -// We also write this in one go to the Keccak sponge, which is at most 1600 bits #define BUFLEN 512u #ifdef __cplusplus @@ -25,11 +24,6 @@ struct infnoise_context { uint32_t entropyThisTime; const char *message; bool errorFlag; - //uint8_t keccakState[KeccakPermutationSizeInBytes]; - - // used in multiplier mode to keep track of bytes to be put out - uint32_t bytesGiven; - uint32_t bytesWritten; }; typedef struct _infnoise_devlist_node_t infnoise_devlist_node_t; @@ -56,11 +50,11 @@ infnoise_devlist_node_t* listUSBDevices(const char **message); * 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) + * - blake3: use BLAKE3 (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); +bool initInfnoise(struct infnoise_context *context, char *serial, bool blake3, bool debug); /* @@ -74,7 +68,6 @@ void deinitInfnoise(struct infnoise_context *context); /* * 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. - * (64 byte for normal operation or 128byte for multiplier mode) * * After every read operation, the infnoise_context's errorFlag must be checked, * and the data from this call has to be discarded when it returns true! @@ -85,11 +78,10 @@ void deinitInfnoise(struct infnoise_context *context); * - 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 byte-array */ -uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier); +uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw); #ifdef __cplusplus } diff --git a/software/libinfnoise_private.h b/software/libinfnoise_private.h index 6c10c34..2302439 100644 --- a/software/libinfnoise_private.h +++ b/software/libinfnoise_private.h @@ -70,7 +70,6 @@ uint32_t extractBytes(uint8_t *bytes, uint32_t length, uint8_t *inBuf, const cha bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, const char **message); -uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, uint32_t *bytesGiven, uint32_t *bytesWritten, bool raw, - uint32_t outputMultiplier); +uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy, bool raw); #endif