From 3e04d0993717d2b5fb51883065b44981db107e5d Mon Sep 17 00:00:00 2001 From: Manuel Domke Date: Sun, 22 Apr 2018 00:39:30 +0200 Subject: [PATCH] bats tests for the driver + libinfnoise cleanup --- .gitmodules | 6 ++ software/examples/README.md | 30 +-------- software/infnoise.c | 4 +- software/libinfnoise.c | 34 +++++----- software/tests/README | 1 + software/tests/infnoise.bats | 87 +++++++++++++++++++++++++ software/tests/test_helper/bats-assert | 1 + software/tests/test_helper/bats-support | 1 + 8 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 .gitmodules create mode 100644 software/tests/README create mode 100644 software/tests/infnoise.bats create mode 160000 software/tests/test_helper/bats-assert create mode 160000 software/tests/test_helper/bats-support diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..669af4d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "software/tests/test_helper/bats-support"] + path = software/tests/test_helper/bats-support + url = https://github.com/ztombol/bats-support +[submodule "software/tests/test_helper/bats-assert"] + path = software/tests/test_helper/bats-assert + url = https://github.com/ztombol/bats-assert diff --git a/software/examples/README.md b/software/examples/README.md index fe95b01..9fb063f 100644 --- a/software/examples/README.md +++ b/software/examples/README.md @@ -1,30 +1,6 @@ # Usage examples for Infinite Noise -## Driver (binary) - -### Command-Line - -Raw output to file: - - infnoise --raw > output.txt - -Whitened output to file: - - infnoise > output.txt - -Whietened, mutliplied output to file: - - infnoise --multiplier 10 > output.txt - -Debug mode: - - infnoise --debug --no-output - -/dev/random mode: - - infnoise --debug --dev-random (--multiplier) - -### Integrate +## Integrate the binary to python See the python examples `serial-numbers.py` and `randomserver.py` to see how you could integrate it with python. @@ -42,9 +18,9 @@ This simple version just prints the serials to stdout. Call like this: A simple webserver based on the web.py framework to serve random data via a REST interface. An example is hosted at https://rng.13-37.org (running on a Raspberry Pi in Amsterdam, thanks to pcextreme.nl!) -It has only two resources: `/get` and `/status`. +It has only two resources: `/get` and `/status`. -## Library +## libinfnoise TODO diff --git a/software/infnoise.c b/software/infnoise.c index 8ab6d10..cde89bd 100644 --- a/software/infnoise.c +++ b/software/infnoise.c @@ -176,12 +176,10 @@ int main(int argc, char **argv) uint8_t keccakState[KeccakPermutationSizeInBytes]; KeccakInitializeState(keccakState); - uint8_t result[1024]; // only used in noOutput mode (and libinfnoise) - uint64_t totalBytesWritten = 0u; while(true) { uint64_t prevTotalBytesWritten = totalBytesWritten; - uint64_t bytesWritten = readData_private(&ftdic, keccakState, result, &message, opts.noOutput, opts.raw, opts.outputMultiplier, opts.devRandom); // calling libinfnoise's private readData method + uint64_t bytesWritten = readData_private(&ftdic, keccakState, NULL, &message, opts.noOutput, opts.raw, opts.outputMultiplier, opts.devRandom); // calling libinfnoise's private readData method if (totalBytesWritten == (unsigned long)-1) { fputs(message, stderr); diff --git a/software/libinfnoise.c b/software/libinfnoise.c index ec50f75..817d6ea 100644 --- a/software/libinfnoise.c +++ b/software/libinfnoise.c @@ -88,8 +88,9 @@ uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uin if (!noOutput) { outputBytes(bytes, BUFLEN/8u, entropy, writeDevRandom); } else { - memcpy(result, bytes, BUFLEN/8u * sizeof(uint8_t)); - //result=bytes; + if (result != NULL) { + memcpy(result, bytes, BUFLEN/8u * sizeof(uint8_t)); + } } return BUFLEN/8u; } @@ -109,10 +110,12 @@ uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uin if (!noOutput) { outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom); } else { - memcpy(result, dataOut, entropy/8u * sizeof(uint8_t)); + if (result != NULL) { + memcpy(result, dataOut, entropy/8u * sizeof(uint8_t)); + } } return entropy/8u; - } // todo: write to result array + } // Output 256*outputMultipler bits. uint32_t numBits = outputMultiplier*256u; @@ -132,16 +135,12 @@ uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uin if (!noOutput) { outputBytes(dataOut, bytesToWrite, entropyThisTime, writeDevRandom); } else { - // append data in result array until we have finished squeezing the keccak sponge - // its important to have an result array of the approriate size: outputMultiplier*32 - //fprintf(stderr, "bytes written: %d\n", bytesWritten); - //fprintf(stderr, "bytes to write: %d\n", bytesToWrite); - - //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work + //memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work? // alternative: loop through dataOut and append array elements to result.. - for (uint32_t i =0; i < bytesToWrite; i++ ) { - fprintf(stderr, " result[%d] = dataOut[%d];\n", bytesWritten + i, i); - result[bytesWritten + i] = dataOut[i]; + if (result != NULL) { + for (uint32_t i =0; i < bytesToWrite; i++ ) { + result[bytesWritten + i] = dataOut[i]; + } } } bytesWritten += bytesToWrite; @@ -155,7 +154,6 @@ uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint8_t *result, uin fprintf(stderr, "Internal error outputing bytes\n"); exit(1); } - fprintf(stderr, "bytes written: %d\n", bytesWritten); return bytesWritten; } @@ -364,12 +362,12 @@ int main() { bool debug = false; // calculate output size based on the parameters: - // when using the multiplier, we need a result array of max 1024 bytes - otherwise 64(BUFLEN/8) bytes + // 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 = 1024; // optimize? + resultSize = multiplier*32u; } fprintf(stderr, "%d\n", resultSize); @@ -381,10 +379,10 @@ int main() { uint64_t bytesWritten = 0u; bytesWritten = readData(&ftdic, keccakState, result, multiplier); - // check for -1! + // 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 but..) + // 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); } } diff --git a/software/tests/README b/software/tests/README new file mode 100644 index 0000000..888bb81 --- /dev/null +++ b/software/tests/README @@ -0,0 +1 @@ +bats tests for the binary driver. diff --git a/software/tests/infnoise.bats b/software/tests/infnoise.bats new file mode 100644 index 0000000..2bebe98 --- /dev/null +++ b/software/tests/infnoise.bats @@ -0,0 +1,87 @@ +#!/usr/bin/env bats + +load 'test_helper/bats-support/load' +load 'test_helper/bats-assert/load' + +# Tests for the infnoise binary + +@test "test --raw output for expected entropy" { + # capture some data + TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX` + timeout 5s ./infnoise --raw > $TMP_FILE || true + + # run ent + run ent $TMP_FILE + + assert_line --index 0 --regexp '^Entropy = 7.2[5-9][0-9]+ bits per byte.$' + + # cleanup + rm $TMP_FILE +} + +@test "test whitened output for expected entropy" { + # capture some data + TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX` + timeout 5s ./infnoise > $TMP_FILE || true + + # run ent + run ent $TMP_FILE + + # check ent's result + assert_line --index 0 --regexp '^Entropy = 7.99[0-9]+ bits per byte.$' + + # cleanup + rm $TMP_FILE +} + +@test "test whitened output (multiplier=10) for expected entropy" { + # capture some data + TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX` + timeout 5s ./infnoise --multiplier 10 > $TMP_FILE || true + + # run ent + run ent $TMP_FILE + + assert_line --index 0 --regexp '^Entropy = 7.99[0-9]+ bits per byte.$' + + # cleanup + rm $TMP_FILE +} + +@test "test --no-output --debug" { + # capture some data + TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX` + run timeout 5s ./infnoise --no-output --debug + + echo $output + [ "$status" -eq 124 ] + + assert_line --index 0 --regexp '^Generated 1048576 bits. OK to use data. Estimated entropy per bit: 0\.[0-8][6-8][0-9]+, estimated K: 1\.8[1-5][0-9]+$' + assert_line --index 1 --regexp '^num1s:50.[0-9]+%, even misfires:0.[0-1][0-9]+%, odd misfires:0.[0-1][0-9]+%$' +} + +@test "test --list-devices" { + run ./infnoise --list-devices + echo $output + [ "$status" -eq 0 ] + + # FTDI serial: + assert_line --index 1 --regexp '^Manufacturer: FTDI, Description: FT240X USB FIFO, Serial: [0-9A-Z]+$' + + # 13-37.org serial: + assert_line --index 0 --regexp '^Manufacturer: 13-37.org, Description: Infinite Noise TRNG, Serial: [0-9A-F]+$' +} + +@test "test --serial with not connected serial (results in error)" { + run ./infnoise --serial 4711 + echo $output + [ "$status" -eq 1 ] + [ "${lines[0]}" = "Can't find Infinite Noise Multiplier. Try running as super user?" ] +} + +@test "test --help" { + run ./infnoise --help + echo $output + [ "$status" -eq 0 ] + [ "${lines[0]}" = "Usage: infnoise [options]" ] +} diff --git a/software/tests/test_helper/bats-assert b/software/tests/test_helper/bats-assert new file mode 160000 index 0000000..9f88b42 --- /dev/null +++ b/software/tests/test_helper/bats-assert @@ -0,0 +1 @@ +Subproject commit 9f88b4207da750093baabc4e3f41bf68f0dd3630 diff --git a/software/tests/test_helper/bats-support b/software/tests/test_helper/bats-support new file mode 160000 index 0000000..004e707 --- /dev/null +++ b/software/tests/test_helper/bats-support @@ -0,0 +1 @@ +Subproject commit 004e707638eedd62e0481e8cdc9223ad471f12ee