compiles again
This commit is contained in:
@@ -28,10 +28,13 @@ confirmed.
|
||||
#include <time.h>
|
||||
#include "healthcheck.h"
|
||||
|
||||
#define INM_MIN_DATA 10000
|
||||
#define INM_MIN_SAMPLE_SIZE 100
|
||||
#define INM_ACCURACY 1.05
|
||||
#define INM_MAX_SEQUENCE 5
|
||||
#define INM_MAX_COUNT (1 << 14)
|
||||
// Matches the Keccac sponge size
|
||||
#define INM_MAX_ENTROPY 1600
|
||||
|
||||
static uint8_t inmN;
|
||||
static uint32_t inmPrevBits;
|
||||
@@ -44,6 +47,7 @@ static uint32_t inmNumBitsOfEntropy;
|
||||
static double inmCurrentProbability;
|
||||
static uint64_t inmTotalBits;
|
||||
static bool inmPrevBit;
|
||||
static uint32_t inmEntropyLevel;
|
||||
|
||||
// Free memory used by the health check.
|
||||
void inmHealthCheckStop(void) {
|
||||
@@ -61,6 +65,7 @@ static void resetStats(void) {
|
||||
inmNumBitsCounted = 0;
|
||||
inmCurrentProbability = 1.0;
|
||||
inmNumBitsOfEntropy = 0;
|
||||
inmEntropyLevel = 0;
|
||||
}
|
||||
|
||||
// Initialize the health check. N is the number of bits used to predict the next bit.
|
||||
@@ -97,10 +102,10 @@ static void scaleStats(void) {
|
||||
inmZeros[i] >>= 1;
|
||||
inmOnes[i] >>= 1;
|
||||
}
|
||||
if(inmNumBitsSampled > 20000) {
|
||||
inmNumBitsCounted = inmNumBitsCounted*(uint64_t)20000/inmNumBitsSampled;
|
||||
inmNumBitsOfEntropy = inmNumBitsOfEntropy*(uint64_t)20000/inmNumBitsSampled;
|
||||
inmNumBitsSampled = 20000;
|
||||
if(inmNumBitsSampled > 2*INM_MIN_DATA) {
|
||||
inmNumBitsCounted = inmNumBitsCounted*(uint64_t)2*INM_MIN_DATA/inmNumBitsSampled;
|
||||
inmNumBitsOfEntropy = inmNumBitsOfEntropy*(uint64_t)2*INM_MIN_DATA/inmNumBitsSampled;
|
||||
inmNumBitsSampled = 2*INM_MIN_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +127,9 @@ bool inmHealthCheckAddBit(bool bit) {
|
||||
while(inmCurrentProbability <= 0.5) {
|
||||
inmCurrentProbability *= 2.0;
|
||||
inmNumBitsOfEntropy++;
|
||||
if(inmHealthCheckOkToUseData() && inmEntropyLevel < INM_MAX_ENTROPY) {
|
||||
inmEntropyLevel++;
|
||||
}
|
||||
}
|
||||
//printf("probability:%f\n", inmCurrentProbability);
|
||||
inmNumBitsCounted++;
|
||||
@@ -145,15 +153,15 @@ bool inmHealthCheckAddBit(bool bit) {
|
||||
return false;
|
||||
}
|
||||
//printf("prevBits: %x\n", inmPrevBits);
|
||||
if(inmNumBitsSampled < 10000) {
|
||||
if(inmNumBitsSampled < INM_MIN_DATA) {
|
||||
return true; // Not enough data yet to test
|
||||
}
|
||||
if(inmNumBitsSampled == 10000 && inmNumBitsCounted < 9900) {
|
||||
if(inmNumBitsSampled == INM_MIN_DATA && inmNumBitsCounted < INM_MIN_DATA*0.99) {
|
||||
// Wait until we have enough data to start measuring entropy
|
||||
resetStats();
|
||||
return true;
|
||||
}
|
||||
if(inmNumBitsSampled == 10000) {
|
||||
if(inmNumBitsSampled == INM_MIN_DATA) {
|
||||
printf("Generated a total of %lu bits to initialize health check\n", inmTotalBits);
|
||||
}
|
||||
// Check the entropy is in line with expectations
|
||||
@@ -169,7 +177,7 @@ bool inmHealthCheckAddBit(bool bit) {
|
||||
// Once we have enough samples, we know that entropyPerBit = log(K)/log(2), so
|
||||
// K must be 2^entryopPerBit.
|
||||
double inmHealthCheckEstimateK(void) {
|
||||
if(inmNumBitsOfEntropy <= 10000) {
|
||||
if(inmNumBitsOfEntropy < INM_MIN_DATA) {
|
||||
return inmK;
|
||||
}
|
||||
double entropyPerBit = (double)inmNumBitsOfEntropy/inmNumBitsCounted;
|
||||
@@ -179,12 +187,31 @@ double inmHealthCheckEstimateK(void) {
|
||||
// Once we have enough samples, we know that entropyPerBit = log(K)/log(2), so
|
||||
// K must be 2^entryopPerBit.
|
||||
double inmHealthCheckEstimateEntropyPerBit(void) {
|
||||
if(inmNumBitsOfEntropy <= 10000) {
|
||||
if(inmNumBitsSampled < INM_MIN_DATA) {
|
||||
return inmExpectedEntropyPerBit;
|
||||
}
|
||||
return (double)inmNumBitsOfEntropy/inmNumBitsCounted;
|
||||
}
|
||||
|
||||
// Return true if the health checker has enough data to verify proper operation of the INM.
|
||||
bool inmHealthCheckOkToUseData(void) {
|
||||
return inmNumBitsSampled >= INM_MIN_DATA;
|
||||
}
|
||||
|
||||
// Just return the entropy level added so far in bytes;
|
||||
uint32_t inmHealthCheckGetEntropyLevel(void) {
|
||||
return inmEntropyLevel/8;
|
||||
}
|
||||
|
||||
// Reduce the entropy level by numBytes.
|
||||
void inmHealthCheckReduceEntropyLevel(uint32_t numBytes) {
|
||||
if(numBytes*8 > inmEntropyLevel) {
|
||||
fprintf(stderr, "Entropy pool underflow\n");
|
||||
exit(1);
|
||||
}
|
||||
inmEntropyLevel -= numBytes*8;
|
||||
}
|
||||
|
||||
#ifdef TEST_HEALTHCHECK
|
||||
|
||||
// Print the tables of statistics.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
bool inmHealthCheckStart(uint8_t N, double K);
|
||||
void inmHealthCheckStop(void);
|
||||
bool inmHealthCheckAddBit(bool bit);
|
||||
bool inmHealthCheckOkToUseData(void);
|
||||
double inmHealthCheckEstimateK(void);
|
||||
double inmHealthCheckEstimateEntropyPerBit(void);
|
||||
// Returns number of bytes of entropy added so far
|
||||
uint32_t inmHealthCheckGetEntropyLevel(void);
|
||||
void inmHealthCheckReduceEntropyLevel(uint32_t numBytes);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/* hello-ftdi.c: flash LED connected between CTS and GND.
|
||||
This example uses the libftdi API.
|
||||
Minimal error checking; written for brevity, not durability. */
|
||||
/* Driver for the Infinite Noise Multiplier USB stick */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ftdi.h>
|
||||
#include "healthcheck.h"
|
||||
#include "KeccakF-1600-interface.h"
|
||||
|
||||
// Must be multiple of 64
|
||||
#define BUFLEN 64
|
||||
//#define BUFLEN 1
|
||||
|
||||
#define COMP1 1
|
||||
#define COMP2 4
|
||||
@@ -18,12 +18,92 @@
|
||||
// Add bits are outputs, except COMP1 and COMP2
|
||||
#define MASK (0xff & ~(1 << COMP1) & ~(1 << COMP2))
|
||||
|
||||
int main()
|
||||
// Extract the INM output from the data received. Basically, either COMP1 or COMP2
|
||||
// changes, not both, so alternate reading bits from them. We get 1 INM bit of output
|
||||
// per byte read. Feed bits from the INM to the health checker.
|
||||
static void extractBytes(uint8_t *bytes, uint8_t *inBuf, bool raw) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < BUFLEN/8; i++) {
|
||||
uint32_t j;
|
||||
uint8_t byte = 0;
|
||||
for(j = 0; j < 8; j++) {
|
||||
byte <<= 1;
|
||||
uint8_t bit = 0;
|
||||
if(j & 1) {
|
||||
// SWEN2 is enabled on odd cycles. We should read COMP1 since it's stable
|
||||
if(bytes[i*8 + j] & (1 << COMP1)) {
|
||||
bit = 1;
|
||||
}
|
||||
} else {
|
||||
// SWEN1 is enabled on even cycles. We should read COMP2 since it's stable
|
||||
if(bytes[i*8 + j] & (1 << COMP1)) {
|
||||
bit = 1;
|
||||
}
|
||||
}
|
||||
byte |= bit;
|
||||
// This is a good place to feed the bit from the INM to the health checker.
|
||||
if(!raw && !inmHealthCheckAddBit(bit)) {
|
||||
fprintf(stderr, "Health check of Infinite Noise Multiplier failed!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
bytes[i] = byte;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the new bytes through the health checker and also into the Keccak sponge.
|
||||
// Output bytes from the sponge only if the health checker says it's OK, and only
|
||||
// output half the entropy we get from the INM, just to be paranoid.
|
||||
static void processBytes(uint8_t *keccakState, uint8_t *bytes, bool raw) {
|
||||
if(raw) {
|
||||
// In raw mode, we disable the health check and whitening, and just output raw
|
||||
// data from the INM.
|
||||
if(fwrite(bytes, 1, BUFLEN/8, stdout) != BUFLEN/8) {
|
||||
fprintf(stderr, "Unable to write output from Infinite Noise Multiplier\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
uint32_t i;
|
||||
for(i = 0; i < BUFLEN/64; i++) {
|
||||
// It's always OK to absorb bytes, even if they are not verified for randomness
|
||||
KeccakAbsorb(keccakState, bytes + i*8, 1);
|
||||
if(inmHealthCheckOkToUseData() && inmHealthCheckGetEntropyLevel() >= 16) {
|
||||
// Only output byes if we have enough entropy and health check passes
|
||||
// Also, we output data at 1/2 the rate of entropy added to the sponge
|
||||
uint8_t dataOut[8];
|
||||
KeccakExtract(keccakState, dataOut, 1);
|
||||
if(fwrite(dataOut, 1, 8, stdout) != 8) {
|
||||
fprintf(stderr, "Unable to write output from Infinite Noise Multiplier\n");
|
||||
exit(1);
|
||||
}
|
||||
inmHealthCheckReduceEntropyLevel(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ftdi_context ftdic;
|
||||
bool raw = false;
|
||||
|
||||
/* Initialize context for subsequent function calls */
|
||||
// Process arguments
|
||||
if(argc > 2 || (argc == 2 && strcmp(argv[1], "--raw"))) {
|
||||
fprintf(stderr, "Usage: infnoise [--raw]\n");
|
||||
return 1;
|
||||
}
|
||||
if(argc == 2) {
|
||||
raw = true;
|
||||
}
|
||||
|
||||
// Initialize FTDI context
|
||||
ftdi_init(&ftdic);
|
||||
if(!inmHealthCheckStart(7, 1.82)) {
|
||||
puts("Can't intialize health checker\n");
|
||||
return 1;
|
||||
}
|
||||
uint8_t keccakState[KeccakPermutationSizeInBytes];
|
||||
KeccakInitializeState(keccakState);
|
||||
|
||||
/* Open FTDI device based on FT232R vendor & product IDs */
|
||||
if(ftdi_usb_open(&ftdic, 0x0403, 0x6015) < 0) {
|
||||
@@ -31,7 +111,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Try to set high baud rate */
|
||||
// Set high baud rate
|
||||
int rc = ftdi_set_baudrate(&ftdic, 3000000);
|
||||
if(rc == -1) {
|
||||
puts("Invalid baud rate\n");
|
||||
@@ -44,8 +124,7 @@ int main()
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable bitbang mode with 4 out, 4 in */
|
||||
//rc = ftdi_set_bitmode(&ftdic, 0xf, BITMODE_BITBANG);
|
||||
// Enable syncrhonous bitbang mode
|
||||
rc = ftdi_set_bitmode(&ftdic, MASK, BITMODE_SYNCBB);
|
||||
if(rc == -1) {
|
||||
puts("Can't enable bit-bang mode\n");
|
||||
@@ -56,15 +135,14 @@ int main()
|
||||
}
|
||||
|
||||
/* Endless loop: invert LED state, write output, pause 1 second */
|
||||
int i = 0;
|
||||
unsigned char outBuf[BUFLEN], inBuf[BUFLEN];
|
||||
uint32_t i;
|
||||
uint8_t outBuf[BUFLEN], inBuf[BUFLEN];
|
||||
for(i = 0; i < BUFLEN; i++) {
|
||||
// Alternate Ph1 and Ph2 - maybe should have both off in between
|
||||
outBuf[i] = i & 1? (1 << SWEN2) : (1 << SWEN1);
|
||||
//outBuf[i] = i;
|
||||
}
|
||||
i = 0;
|
||||
for(;;) {
|
||||
while(true) {
|
||||
if(ftdi_write_data(&ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||
puts("USB write failed\n");
|
||||
return -1;
|
||||
@@ -73,9 +151,9 @@ int main()
|
||||
puts("USB read failed\n");
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
if((i & 0xfff) == 0) {
|
||||
printf("read %u, last byte == %u\n", 4096*BUFLEN, inBuf[BUFLEN-1]);
|
||||
}
|
||||
uint8_t bytes[BUFLEN/8];
|
||||
extractBytes(bytes, inBuf, raw);
|
||||
processBytes(keccakState, bytes, raw);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user