Merge pull request #70 from 13-37-org/master

refactoring to libinfnoise complete
This commit is contained in:
Manuel Domke
2018-09-05 07:50:24 +02:00
committed by GitHub
14 changed files with 666 additions and 447 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 <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. 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
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 <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. 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
Note: The options --daemon and --pidfile are only implemented in the Linux version.

View File

@@ -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

View File

@@ -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:

View File

@@ -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;

View File

@@ -1,46 +0,0 @@
/*
This is a very simple example to use libinfnoise in raw output mode.
*/
#include <stdio.h>
#include <ftdi.h>
#include <libinfnoise.h>
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;
}

View File

@@ -0,0 +1,58 @@
/*
This is a simple example to use libinfnoise with whitened and multiplied output.
*/
#include <stdio.h>
#include <ftdi.h>
#include <libinfnoise.h>
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;
}

View File

@@ -8,9 +8,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
#include <fcntl.h>
#endif
#include <string.h>
#include <time.h>
#include <sys/types.h>
@@ -18,41 +20,81 @@
#include <getopt.h>
#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;
}
int main(int argc, char **argv) {
struct ftdi_context ftdic;
struct infnoise_context context;
struct opt_struct opts;
int ch;
bool multiplierAssigned = false;
@@ -63,56 +105,56 @@ int main(int argc, char **argv) {
while ((ch = getopt_long(argc, argv, "rDRnm:p:s:dlvh", longopts, NULL)) !=
-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;
}
}
@@ -147,15 +189,15 @@ int main(int argc, char **argv) {
}
}
if (opts.debug == false) {
if (!opts.debug) {
if (getenv("INFNOISE_DEBUG") != NULL) {
if (!strcmp("true",getenv("INFNOISE_DEBUG"))) {
if (!strcmp("true", getenv("INFNOISE_DEBUG"))) {
opts.debug = true;
}
}
}
if (multiplierAssigned == false) {
if (!multiplierAssigned) {
if (getenv("INFNOISE_MULTIPLIER") != NULL) {
int tmpOutputMult = atoi(getenv("INFNOISE_MULTIPLIER"));
if (tmpOutputMult < 0) {
@@ -167,7 +209,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
}
@@ -178,33 +220,39 @@ int main(int argc, char **argv) {
return 0;
}
char *message = "no data?";
bool errorFlag = false;
if (opts.listDevices) {
if(!listUSBDevices(&ftdic, &message)) {
fputs(message, stderr);
devlist_node devlist = listUSBDevices(&context.message);
if (devlist == NULL) {
fprintf(stderr, "Error: %s\n", context.message);
return 1;
}
//fputs(message, stdout); // todo: put list of devices to &message and print here, not in libinfnoise
devlist_node curdev = NULL;
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;
}
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);
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";
return 0;
fprintf(stderr, "Error: %s\n", context.message);
return 1;
#endif
}
@@ -212,25 +260,45 @@ int main(int argc, char **argv) {
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
}
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
uint64_t resultSize;
if (opts.outputMultiplier == 0 || opts.raw) {
resultSize = BUFLEN / 8u;
} else {
resultSize = opts.outputMultiplier * 32u;
}
//fprintf(stderr, "resultsize: %lu\n", resultSize);
// endless loop
uint64_t totalBytesWritten = 0u;
while(true) {
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
while (true) {
uint8_t result[resultSize];
uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier);
totalBytesWritten += bytesWritten;
if (errorFlag) {
fprintf(stderr, "Error: %s\n", message);
if (context.errorFlag) {
fprintf(stderr, "Error: %s\n", context.message);
return 1;
}
if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten);
if (!opts.noOutput) {
if (!outputBytes(result, bytesWritten, 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) * (totalBytesWritten + bytesWritten / (1u << 20u))) {
fprintf(stderr, "Output %lu bytes\n", (unsigned long) totalBytesWritten);
}
}
return 0;
}

View File

@@ -24,4 +24,9 @@ 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);

View File

@@ -16,7 +16,6 @@
#include <sys/types.h>
#include <ftdi.h>
#include "libinfnoise_private.h"
#include "libinfnoise.h"
#include "KeccakF-1600-interface.h"
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
@@ -24,19 +23,21 @@
#endif
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) {
context->message="";
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;
}
}
@@ -48,28 +49,30 @@ bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool
}
// let healthcheck collect some data
uint32_t maxWarmupRounds = 500;
uint32_t maxWarmupRounds = 5000;
uint32_t warmupRounds = 0;
bool errorFlag = false;
while(!inmHealthCheckOkToUseData()) {
readData_private(ftdic, NULL, message, &errorFlag, false, true, 0, false);
//bool errorFlag = false;
while (!inmHealthCheckOkToUseData()) {
readData(context, NULL, true, 0);
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;
}
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);
}
}
@@ -80,19 +83,19 @@ void prepareOutputBuffer() {
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;
@@ -103,90 +106,26 @@ 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
//fputs("room?", stderr);
inmWaitForPoolToHaveRoom();
//fputs("room!", stderr);
//printf("length: - %ul\n", length);
//printf("entropy: - %ul\n", entropy);
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,
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) {
//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 (!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));
}
if (result != NULL) {
memcpy(result, bytes, BUFLEN / 8u * sizeof(uint8_t));
}
return BUFLEN/8u;
return BUFLEN / 8u;
}
// Note that BUFLEN has to be less than 1600 by enough to make the sponge secure,
@@ -196,112 +135,96 @@ 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);
if(outputMultiplier == 0u) {
uint8_t dataOut[16u*8u];
uint8_t dataOut[1024u];
KeccakAbsorb(keccakState, bytes, BUFLEN / 64u);
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));
}
KeccakExtract(keccakState, dataOut, (*entropy + 63u) / 64u);
if (result != NULL) {
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]; // ???
// 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.
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];
}
}
// Output up to 1024 bits at a time.
uint32_t bytesToWrite = 1024u / 8u;
if (bytesToWrite > *numBits / 8u) {
bytesToWrite = *numBits / 8u;
}
//fprintf(stderr, "bytesWritten: %ul\n", bytesWritten);
//fprintf(stderr, "entropy: %ul\n", entropy);
KeccakExtract(keccakState, result, bytesToWrite / 8u);
KeccakPermutation(keccakState);
*bytesWritten = bytesToWrite;
*numBits -= bytesToWrite * 8u;
}
return *bytesWritten;
}
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;
}
//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;
int32_t nanoseconds = end->tv_nsec - start->tv_nsec;
return seconds * 1.0e6 + nanoseconds / 1000.0;
}
bool isSuperUser(void) {
return (geteuid() == 0);
}
// Return a list of all infinite noise multipliers found.
bool listUSBDevices(struct ftdi_context *ftdic, char** message) {
ftdi_init(ftdic);
devlist_node listUSBDevices(char **message) {
struct ftdi_context ftdic;
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);
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 = malloc(sizeof(struct infnoise_devlist_node));
devlist_node current_entry = return_list;
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?";
return false;
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
return NULL;
} else {
//todo: *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 false;
}
// print to stdout
printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial);
current_entry->id = i;
strcpy(current_entry->serial, serial);
strcpy(current_entry->manufacturer, manufacturer);
strcpy(current_entry->description, description);
if (curdev->next) {
current_entry->next = malloc(sizeof(struct infnoise_devlist_node));
current_entry = current_entry->next;
} else {
current_entry->next = NULL;
}
curdev = curdev->next;
}
return true;
return return_list;
}
// Initialize the Infinite Noise Multiplier USB interface.
@@ -324,7 +247,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
@@ -341,7 +264,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";
@@ -353,119 +276,91 @@ 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) {
return readData_private(ftdic, result, message, errorFlag, false, true, 0, false);
}
uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier) {
// 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!
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);
}
// Output up to 1024 bits at a time.
uint32_t bytesToWrite = 1024u / 8u;
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);
if (bytesToWrite > context->numBits / 8u) {
bytesToWrite = context->numBits / 8u;
}
// write clock signal
if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) {
*message = "USB write failed";
*errorFlag = true;
}
KeccakExtract(keccakState, result, bytesToWrite / 8u);
KeccakPermutation(keccakState);
// 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;
return 0;
}
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);
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);
// write clock signal
if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) {
context->message = "USB write failed";
context->errorFlag = true;
}
//fprintf(stderr, "ERROR1: %ul\n", entropy);
// 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;
}
struct timespec end;
clock_gettime(CLOCK_REALTIME, &end);
uint32_t us = diffTime(&start, &end);
// 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);
return byteswritten;
if (us <= MAX_MICROSEC_FOR_SAMPLES) {
uint8_t bytes[BUFLEN / 8u];
context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag);
if (context->errorFlag) {
// todo: message?
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;
}
#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
// 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

View File

@@ -1,11 +1,13 @@
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(__FreeBSD__)
#include <limits.h>
#else
#include <linux/limits.h>
#endif
#include <ftdi.h>
#include <time.h>
@@ -13,10 +15,65 @@
// 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 entropyThisTime;
char *message;
bool errorFlag;
//uint8_t keccakState[KeccakPermutationSizeInBytes];
bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool keccak, bool debug);
// used in multiplier mode to keep track of bytes to be put out
uint32_t numBits;
uint32_t bytesWritten;
};
uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag);
struct infnoise_devlist_node {
uint8_t id;
char manufacturer[128];
char description[129];
char serial[128];
struct infnoise_devlist_node *next;
};
uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier);
typedef struct infnoise_devlist_node *devlist_node;
/*
* 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);
/*
* 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);

View File

@@ -8,7 +8,7 @@
#endif
#include <ftdi.h>
#include <time.h>
#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);
@@ -48,14 +46,12 @@ 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;
bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial);
bool initializeUSB(struct ftdi_context *ftdic, char **message,char *serial);
void prepareOutputBuffer();
struct timespec;
@@ -63,7 +59,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 readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom);
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);