Merge pull request #35 from runema/opt-struct

Introduce struct for parsed options
This commit is contained in:
Bill
2017-12-23 11:26:51 -08:00
committed by GitHub
6 changed files with 83 additions and 62 deletions

View File

@@ -73,7 +73,9 @@ Options are:
--raw - do not whiten the output
--multiplier <value> - 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
--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 <filename> - write the process ID to a file. If --daemon is used, it is the ID of the background process.
--serial <serial> - use Infinite Noise TRNG/FT240 with the given serial number (see --list-devices)
--list-devices - list available devices

View File

@@ -24,11 +24,11 @@ static bool writePid(int32_t pid, char *fileName) {
return true;
}
void startDaemon(bool daemon, bool pidFile, char *fileName) {
if(!daemon) {
void startDaemon(struct opt_struct* opts) {
if(!opts->daemon) {
// No backgrounding, optionslly write current PID
if(pidFile) {
writePid(getpid(), fileName);
if(opts->pidFileName != NULL) {
writePid(getpid(), opts->pidFileName);
}
return;
}
@@ -38,8 +38,8 @@ void startDaemon(bool daemon, bool pidFile, char *fileName) {
exit(1);
} else if(pid > 0) {
// Parent
if(pidFile) {
if(!writePid(pid, fileName)) {
if(opts->pidFileName != NULL) {
if(!writePid(pid, opts->pidFileName)) {
exit(1);
}
}

View File

@@ -91,11 +91,11 @@ static void resetStats(void) {
// Initialize the health check. N is the number of bits used to predict the next bit.
// At least 8 bits must be used, and no more than 30. In general, we should use bits
// large enough so that INM output will be uncorrelated with bits N samples back in time.
bool inmHealthCheckStart(uint8_t N, double K, bool debug) {
bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts) {
if(N < 1u || N > 30u) {
return false;
}
inmDebug = debug;
inmDebug = opts->debug;
inmNumBitsOfEntropy = 0u;
inmCurrentProbability = 1.0;
inmK = K;

View File

@@ -49,14 +49,14 @@ static uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf) {
}
// Write the bytes to either stdout, or /dev/random.
static void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom) {
if(!writeDevRandom) {
static void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, struct opt_struct *opts) {
if(!opts->devRandom) {
if(fwrite(bytes, 1, length, stdout) != length) {
fputs("Unable to write output from Infinite Noise Multiplier\n", stderr);
exit(1);
}
} else {
inmWaitForPoolToHaveRoom();
inmWaitForPoolToHaveRoom(opts);
inmWriteEntropyToPool(bytes, length, entropy);
}
}
@@ -67,16 +67,15 @@ static void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool
// outputMultiplier is 0, we output only as many bits as we measure in entropy.
// This allows a user to generate hundreds of MiB per second if needed, for use
// as cryptogrpahic keys.
static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entropy, bool raw,
bool writeDevRandom, uint32_t outputMultiplier) {
static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entropy, struct opt_struct* opts) {
//Use the lower of the measured entropy and the provable lower bound on
//average entropy.
if(entropy > inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY) {
entropy = inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY;
}
if(raw) {
if(opts->raw) {
// In raw mode, we just output raw data from the INM.
outputBytes(bytes, BUFLEN/8u, entropy, writeDevRandom);
outputBytes(bytes, BUFLEN/8u, entropy, opts);
return BUFLEN/8u;
}
// Note that BUFLEN has to be less than 1600 by enough to make the sponge secure,
@@ -88,14 +87,14 @@ static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entr
// Keccak-1600 uses 64-bit "lanes".
KeccakAbsorb(keccakState, bytes, BUFLEN/64u);
uint8_t dataOut[16u*8u];
if(outputMultiplier == 0u) {
if(opts->outputMultiplier == 0u) {
// Output all the bytes of entropy we have
KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u);
outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom);
outputBytes(dataOut, entropy/8u, entropy & 0x7u, opts);
return entropy/8u;
}
// Output 256*outputMultipler bytes.
uint32_t numBits = outputMultiplier*256u;
uint32_t numBits = opts->outputMultiplier*256u;
uint32_t bytesWritten = 0u;
while(numBits > 0u) {
// Write up to 1024 bits at a time.
@@ -108,7 +107,7 @@ static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entr
if(entropyThisTime > 8u*bytesToWrite) {
entropyThisTime = 8u*bytesToWrite;
}
outputBytes(dataOut, bytesToWrite, entropyThisTime, writeDevRandom);
outputBytes(dataOut, bytesToWrite, entropyThisTime, opts);
bytesWritten += bytesToWrite;
numBits -= bytesToWrite*8u;
entropy -= entropyThisTime;
@@ -116,7 +115,7 @@ static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entr
KeccakPermutation(keccakState);
}
}
if(bytesWritten != outputMultiplier*(256u/8u)) {
if(bytesWritten != opts->outputMultiplier*(256u/8u)) {
fprintf(stderr, "Internal error outputing bytes\n");
exit(1);
}
@@ -232,6 +231,19 @@ static bool initializeUSB(struct ftdi_context *ftdic, char **message, char *seri
return true;
}
static void initOpts(struct opt_struct *opts) {
opts->outputMultiplier = 0u;
opts->daemon =
opts->debug =
opts->devRandom =
opts->noOutput =
opts->listDevices =
opts->raw = false;
opts->pidFileName =
opts->serial = NULL;
}
// Return the differnece in the times as a double in microseconds.
static double diffTime(struct timespec *start, struct timespec *end) {
uint32_t seconds = end->tv_sec - start->tv_sec;
@@ -242,29 +254,22 @@ static double diffTime(struct timespec *start, struct timespec *end) {
int main(int argc, char **argv)
{
struct ftdi_context ftdic;
bool raw = false;
bool debug = false;
bool writeDevRandom = false;
bool noOutput = false;
uint32_t outputMultiplier = 0u; // We output all the entropy when outputMultiplier == 0
struct opt_struct opts;
int xArg;
bool multiplierAssigned = false;
bool pidFile = false;
char *pidFileName = NULL;
char *serial = NULL;
bool runDaemon = false;
bool listDevices = false;
initOpts(&opts);
// Process arguments
for(xArg = 1; xArg < argc; xArg++) {
if(!strcmp(argv[xArg], "--raw")) {
raw = true;
opts.raw = true;
} else if(!strcmp(argv[xArg], "--debug")) {
debug = true;
opts.debug = true;
} else if(!strcmp(argv[xArg], "--dev-random")) {
writeDevRandom = true;
opts.devRandom = true;
} else if(!strcmp(argv[xArg], "--no-output")) {
noOutput = true;
opts.noOutput = true;
} else if(!strcmp(argv[xArg], "--multiplier") && xArg+1 < argc) {
xArg++;
multiplierAssigned = true;
@@ -273,26 +278,25 @@ int main(int argc, char **argv)
fputs("Multiplier must be >= 0\n", stderr);
return 1;
}
outputMultiplier = tmpOutputMult;
opts.outputMultiplier = tmpOutputMult;
} else if(!strcmp(argv[xArg], "--pidfile")) {
xArg++;
pidFileName = argv[xArg];
pidFile = true;
if(pidFileName == NULL || !strcmp("",pidFileName)) {
opts.pidFileName = argv[xArg];
if(opts.pidFileName == NULL || !strcmp("", opts.pidFileName)) {
fputs("--pidfile without file name\n", stderr);
return 1;
}
} else if(!strcmp(argv[xArg], "--serial")) {
xArg++;
serial = argv[xArg];
if(serial == NULL || !strcmp("",serial)) {
opts.serial = argv[xArg];
if(opts.serial == NULL || !strcmp("",opts.serial)) {
fputs("--serial without value\n", stderr);
return 1;
}
} else if(!strcmp(argv[xArg], "--daemon")) {
runDaemon = true;
opts.daemon = true;
} else if(!strcmp(argv[xArg], "--list-devices")) {
listDevices = true;
opts.listDevices = true;
} else {
fputs("Usage: infnoise [options]\n"
"Options are:\n"
@@ -310,21 +314,21 @@ int main(int argc, char **argv)
}
}
if(!multiplierAssigned && writeDevRandom) {
outputMultiplier = 2u; // Don't throw away entropy when writing to /dev/random unless told to do so
if(!multiplierAssigned && opts.devRandom) {
opts.outputMultiplier = 2u; // Don't throw away entropy when writing to /dev/random unless told to do so
}
if (listDevices) {
if (opts.listDevices) {
listUSBDevices(&ftdic);
return 0;
}
// Optionally run in the background and optionally write a PID-file
startDaemon(runDaemon, pidFile, pidFileName);
startDaemon(&opts);
if(writeDevRandom) {
inmWriteEntropyStart(BUFLEN/8u, debug);
if(opts.devRandom) {
inmWriteEntropyStart(BUFLEN/8u, &opts);
}
if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) {
if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, &opts)) {
fputs("Can't intialize health checker\n", stderr);
return 1;
}
@@ -333,9 +337,9 @@ int main(int argc, char **argv)
KeccakInitializeState(keccakState);
char *message;
if(!initializeUSB(&ftdic, &message, serial)) {
if(!initializeUSB(&ftdic, &message, opts.serial)) {
// Sometimes have to do it twice - not sure why
if(!initializeUSB(&ftdic, &message, serial)) {
if(!initializeUSB(&ftdic, &message, opts.serial)) {
fputs(message, stderr);
return 1;
}
@@ -368,10 +372,10 @@ int main(int argc, char **argv)
if(us <= MAX_MICROSEC_FOR_SAMPLES) {
uint8_t bytes[BUFLEN/8u];
uint32_t entropy = extractBytes(bytes, inBuf);
if(!noOutput && inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) {
if(!opts.noOutput && inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) {
uint64_t prevTotalBytesWritten = totalBytesWritten;
totalBytesWritten += processBytes(keccakState, bytes, entropy, raw, writeDevRandom, outputMultiplier);
if(debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
totalBytesWritten += processBytes(keccakState, bytes, entropy, &opts);
if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten);
}
}

View File

@@ -30,7 +30,20 @@
// 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);
// Structure for parsed command line options
struct opt_struct {
uint32_t outputMultiplier; // We output all the entropy when outputMultiplier == 0
bool daemon; // Run as daemon?
bool debug; // Print debugging info?
bool devRandom; // Feed /dev/random?
bool noOutput; // Supress output?
bool listDevices; // List possible USB-devices?
bool raw; // No whitening?
char *pidFileName; // Name of optional PID-file
char *serial; // Name of selected device
};
bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts);
void inmHealthCheckStop(void);
bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even);
bool inmHealthCheckOkToUseData(void);
@@ -39,11 +52,11 @@ 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 inmWriteEntropyStart(uint32_t bufLen, struct opt_struct *opts);
void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy);
void inmWaitForPoolToHaveRoom(void);
void inmWaitForPoolToHaveRoom(struct opt_struct *opts);
void inmDumpStats(void);
void startDaemon(bool daemon, bool pidFile, char *fileName);
void startDaemon(struct opt_struct *opts);
bool isSuperUser(void);
extern double inmK, inmExpectedEntropyPerBit;

View File

@@ -40,9 +40,9 @@ static uint32_t readNumberFromFile(char *fileName) {
}
// Open /dev/random
void inmWriteEntropyStart(uint32_t bufLen, bool debug) {
void inmWriteEntropyStart(uint32_t bufLen, struct opt_struct* opts) {
inmBufLen = bufLen;
inmDebug = debug;
inmDebug = opts->debug;
//inmDevRandomFD = open("/dev/random", O_WRONLY);
inmDevRandomFD = open("/dev/random", O_RDWR);
if(inmDevRandomFD < 0) {
@@ -61,7 +61,7 @@ void inmWriteEntropyStart(uint32_t bufLen, bool debug) {
}
// Block until either the entropy pool has room, or 1 second has passed.
void inmWaitForPoolToHaveRoom(void) {
void inmWaitForPoolToHaveRoom(struct opt_struct *opts) {
int ent_count;
struct pollfd pfd = {
.fd = inmDevRandomFD,
@@ -72,6 +72,8 @@ void inmWaitForPoolToHaveRoom(void) {
return;
}
timeout_msec = 1000u; // One second
if (opts->daemon)
timeout_msec *= 60u; // Do not poll aggressively when in the background
poll(&pfd, 1, timeout_msec);
}