Merge pull request #12 from 13-37-org/libinfnoise
merge libinfnoise branch
This commit is contained in:
@@ -20,7 +20,7 @@ RM=rm
|
|||||||
all: libinfnoise.a libinfnoise.so infnoise
|
all: libinfnoise.a libinfnoise.so infnoise
|
||||||
|
|
||||||
infnoise: libinfnoise.a infnoise.o daemon.o
|
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
|
%.o: %.c infnoise.h libinfnoise.h
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ endif
|
|||||||
all: libinfnoise.a libinfnoise.so infnoise
|
all: libinfnoise.a libinfnoise.so infnoise
|
||||||
|
|
||||||
infnoise: libinfnoise.a infnoise.o daemon.o
|
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
|
%.o: %.c infnoise.h libinfnoise.h
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ RM=rm
|
|||||||
all: libinfnoise.a libinfnoise.so infnoise
|
all: libinfnoise.a libinfnoise.so infnoise
|
||||||
|
|
||||||
infnoise: libinfnoise.a infnoise.o daemon.o
|
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
|
%.o: %.c infnoise.h libinfnoise.h
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|||||||
@@ -76,19 +76,19 @@ with the stable release for now.
|
|||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Usage: infnoise [options]
|
Usage: infnoise [options]
|
||||||
Options are:
|
Options are:
|
||||||
--debug - turn on some debug output
|
--debug - turn on some debug output
|
||||||
--dev-random - write entropy to /dev/random instead of stdout
|
--dev-random - write entropy to /dev/random instead of stdout
|
||||||
--raw - do not whiten the output
|
--raw - do not whiten the output
|
||||||
--multiplier <value> - write 256 bits * value for each 512 bits written to the Keccak sponge
|
--multiplier <value> - write 256 bits * value for each 512 bits written to the Keccak sponge
|
||||||
--no-output - do not write random output data
|
--no-output - do not write random output data
|
||||||
--daemon - run in the background. Output should be redirected to a file or
|
--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
|
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.
|
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.
|
--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)
|
--serial <serial> - use Infinite Noise TRNG/FT240 with the given serial number (see --list-devices)
|
||||||
--list-devices - list available devices
|
--list-devices - list available devices
|
||||||
|
|
||||||
Note: The options --daemon and --pidfile are only implemented in the Linux version.
|
Note: The options --daemon and --pidfile are only implemented in the Linux version.
|
||||||
|
|
||||||
181
software/build-scripts/infnoise-gitian.yml
Normal file
181
software/build-scripts/infnoise-gitian.yml
Normal 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
|
||||||
@@ -13,12 +13,15 @@ LDFLAGS= -shared
|
|||||||
|
|
||||||
FTDI := $(shell libftdi-config --libs)
|
FTDI := $(shell libftdi-config --libs)
|
||||||
|
|
||||||
all: libinfnoise-example libinfnoise-example-raw
|
all: libinfnoise-example libinfnoise-example-raw libinfnoise-example-1
|
||||||
|
|
||||||
libinfnoise-example: example.c
|
libinfnoise-example: example.c
|
||||||
$(CC) $(CFLAGS) -o libinfnoise-example example.c $(FTDI) -lm -lrt -linfnoise
|
$(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
|
$(CC) $(CFLAGS) -o libinfnoise-example-raw example-raw.c $(FTDI) -lm -lrt -linfnoise
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -10,27 +10,26 @@ int main()
|
|||||||
{
|
{
|
||||||
// parameters
|
// parameters
|
||||||
char *serial=NULL; // can be set to a specific serial, NULL uses the first found device
|
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)
|
bool initKeccak = false; // initialize Keccak sponge (used for whitening)
|
||||||
uint32_t multiplier = 10u; // multiplier for whitening
|
uint32_t multiplier = 1u; // multiplier for whitening
|
||||||
bool debug = false; // debug mode (health monitor writes to stderr)
|
bool debug = true; // debug mode (health monitor writes to stderr)
|
||||||
|
|
||||||
char *message;
|
|
||||||
bool errorFlag = false;
|
|
||||||
|
|
||||||
// initialize hardware and health monitor
|
// initialize hardware and health monitor
|
||||||
struct ftdi_context ftdic;
|
struct infnoise_context context;
|
||||||
if (!initInfnoise(&ftdic, serial, &message, true, debug)) {
|
fprintf(stdout, "pre-initi: %s\n", "");
|
||||||
fputs(message, stderr);
|
|
||||||
|
if (!initInfnoise(&context, serial, initKeccak, debug)) {
|
||||||
|
fprintf(stdout, "erri: %s\n", "");
|
||||||
|
fputs(context.message, stderr);
|
||||||
return 1; // ERROR
|
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;
|
uint32_t resultSize;
|
||||||
if (multiplier == 0 || initKeccak == false) {
|
if (multiplier == 0 || initKeccak == false) {
|
||||||
resultSize = BUFLEN/8u;
|
resultSize = 512u;
|
||||||
} else {
|
} else {
|
||||||
resultSize = multiplier*32u;
|
resultSize = 1024u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read and print in a loop (until 1M is read)
|
// read and print in a loop (until 1M is read)
|
||||||
@@ -39,18 +38,20 @@ int main()
|
|||||||
uint8_t result[resultSize];
|
uint8_t result[resultSize];
|
||||||
|
|
||||||
// readRawData returns the number of bytes written to result array
|
// readRawData returns the number of bytes written to result array
|
||||||
uint64_t bytesWritten = readData(&ftdic, result, &message, &errorFlag, multiplier);
|
uint64_t bytesWritten = readData(&context, result, !initKeccak, multiplier);
|
||||||
totalBytesWritten += bytesWritten;
|
fprintf(stderr, "infnoise bytes read: %lu\n", bytesWritten);
|
||||||
|
|
||||||
// check for errors
|
// check for errors
|
||||||
// note: bytesWritten is also 0 in this case, but an errorFlag is needed as
|
// 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.
|
// bytesWritten can also be 0 when data hasn't passed the health monitor.
|
||||||
if (errorFlag) {
|
if (context.errorFlag) {
|
||||||
fprintf(stderr, "Error: %s\n", message);
|
fprintf(stderr, "Error: %s\n", context.message);
|
||||||
return 1;
|
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);
|
fwrite(result, 1, bytesWritten, stdout);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
58
software/examples/libinfnoise/example-simple.c
Normal file
58
software/examples/libinfnoise/example-simple.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -8,9 +8,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -18,41 +20,81 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include "infnoise.h"
|
#include "infnoise.h"
|
||||||
#include "libinfnoise.h"
|
#include "libinfnoise.h"
|
||||||
#include "libinfnoise_private.h"
|
|
||||||
#include "KeccakF-1600-interface.h"
|
#include "KeccakF-1600-interface.h"
|
||||||
|
|
||||||
static void initOpts(struct opt_struct *opts) {
|
static void initOpts(struct opt_struct *opts) {
|
||||||
opts->outputMultiplier = 0u;
|
opts->outputMultiplier = 0u;
|
||||||
opts->daemon = false;
|
opts->daemon = false;
|
||||||
opts->debug = false;
|
opts->debug = false;
|
||||||
opts->devRandom = false;
|
opts->devRandom = false;
|
||||||
opts->noOutput = false;
|
opts->noOutput = false;
|
||||||
opts->listDevices = false;
|
opts->listDevices = false;
|
||||||
opts->raw = false;
|
opts->raw = false;
|
||||||
opts->version = false;
|
opts->version = false;
|
||||||
opts->help = false;
|
opts->help = false;
|
||||||
opts->none = false;
|
opts->none = false;
|
||||||
opts->pidFileName =
|
opts->pidFileName =
|
||||||
opts->serial = NULL;
|
opts->serial = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getopt_long(3) options descriptor
|
// 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'},
|
// Write the bytes to either stdout, or /dev/random.
|
||||||
{"debug", no_argument, NULL, 'D'},
|
bool outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, bool writeDevRandom, char **message) {
|
||||||
{"dev-random", no_argument, NULL, 'R'},
|
if (!writeDevRandom) {
|
||||||
{"no-output", no_argument, NULL, 'n'},
|
if (fwrite(bytes, 1, length, stdout) != length) {
|
||||||
{"multiplier", required_argument, NULL, 'm'},
|
*message = "Unable to write output from Infinite Noise Multiplier";
|
||||||
{"pidfile", required_argument, NULL, 'p'},
|
return false;
|
||||||
{"serial", required_argument, NULL, 's'},
|
}
|
||||||
{"daemon", no_argument, NULL, 'd'},
|
} else {
|
||||||
{"list-devices", no_argument, NULL, 'l'},
|
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
{"version", no_argument, NULL, 'v'},
|
// quell compiler warning about unused variable.
|
||||||
{"help", no_argument, NULL, 'h'},
|
static int devRandomFD = -1;
|
||||||
{NULL, 0, NULL, 0}};
|
(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) {
|
int main(int argc, char **argv) {
|
||||||
struct ftdi_context ftdic;
|
struct infnoise_context context;
|
||||||
struct opt_struct opts;
|
struct opt_struct opts;
|
||||||
int ch;
|
int ch;
|
||||||
bool multiplierAssigned = false;
|
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)) !=
|
while ((ch = getopt_long(argc, argv, "rDRnm:p:s:dlvh", longopts, NULL)) !=
|
||||||
-1) {
|
-1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'r':
|
case 'r':
|
||||||
opts.raw = true;
|
opts.raw = true;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
opts.debug = true;
|
opts.debug = true;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
opts.devRandom = true;
|
opts.devRandom = true;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
opts.noOutput = true;
|
opts.noOutput = true;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
multiplierAssigned = true;
|
multiplierAssigned = true;
|
||||||
int tmpOutputMult = atoi(optarg);
|
int tmpOutputMult = atoi(optarg);
|
||||||
if (tmpOutputMult < 0) {
|
if (tmpOutputMult < 0) {
|
||||||
fputs("Multiplier must be >= 0\n", stderr);
|
fputs("Multiplier must be >= 0\n", stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
opts.outputMultiplier = tmpOutputMult;
|
opts.outputMultiplier = tmpOutputMult;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
opts.pidFileName = optarg;
|
opts.pidFileName = optarg;
|
||||||
if (opts.pidFileName == NULL || !strcmp("", opts.pidFileName)) {
|
if (opts.pidFileName == NULL || !strcmp("", opts.pidFileName)) {
|
||||||
fputs("--pidfile without file name\n", stderr);
|
fputs("--pidfile without file name\n", stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
opts.serial = optarg;
|
opts.serial = optarg;
|
||||||
if (opts.serial == NULL || !strcmp("", opts.serial)) {
|
if (opts.serial == NULL || !strcmp("", opts.serial)) {
|
||||||
fputs("--serial without value\n", stderr);
|
fputs("--serial without value\n", stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
opts.daemon = true;
|
opts.daemon = true;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
opts.listDevices = true;
|
opts.listDevices = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
opts.version = true;
|
opts.version = true;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
opts.help = true;
|
opts.help = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
opts.help = true;
|
opts.help = true;
|
||||||
opts.none = 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 (getenv("INFNOISE_DEBUG") != NULL) {
|
||||||
if (!strcmp("true",getenv("INFNOISE_DEBUG"))) {
|
if (!strcmp("true", getenv("INFNOISE_DEBUG"))) {
|
||||||
opts.debug = true;
|
opts.debug = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multiplierAssigned == false) {
|
if (!multiplierAssigned) {
|
||||||
if (getenv("INFNOISE_MULTIPLIER") != NULL) {
|
if (getenv("INFNOISE_MULTIPLIER") != NULL) {
|
||||||
int tmpOutputMult = atoi(getenv("INFNOISE_MULTIPLIER"));
|
int tmpOutputMult = atoi(getenv("INFNOISE_MULTIPLIER"));
|
||||||
if (tmpOutputMult < 0) {
|
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
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *message = "no data?";
|
|
||||||
bool errorFlag = false;
|
|
||||||
if (opts.listDevices) {
|
if (opts.listDevices) {
|
||||||
if(!listUSBDevices(&ftdic, &message)) {
|
devlist_node devlist = listUSBDevices(&context.message);
|
||||||
fputs(message, stderr);
|
if (devlist == NULL) {
|
||||||
|
fprintf(stderr, "Error: %s\n", context.message);
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.devRandom) {
|
if (opts.devRandom) {
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
inmWriteEntropyStart(BUFLEN/8u, opts.debug); // todo: create method in libinfnoise.h for this?
|
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 :-/)
|
// also TODO: check superUser in this mode (it will fail silently if not :-/)
|
||||||
#endif
|
#endif
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
int devRandomFD = open("/dev/random", O_WRONLY);
|
int devRandomFD = open("/dev/random", O_WRONLY);
|
||||||
if(devRandomFD < 0) {
|
if (devRandomFD < 0) {
|
||||||
fprintf(stderr, "Unable to open /dev/random\n");
|
fprintf(stderr, "Unable to open /dev/random\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(devRandomFD);
|
close(devRandomFD);
|
||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
message = "dev/random not supported on macOS";
|
message = "dev/random not supported on macOS";
|
||||||
return 0;
|
fprintf(stderr, "Error: %s\n", context.message);
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,25 +260,45 @@ int main(int argc, char **argv) {
|
|||||||
startDaemon(&opts);
|
startDaemon(&opts);
|
||||||
|
|
||||||
// initialize USB device, health check and Keccak state (see libinfnoise)
|
// initialize USB device, health check and Keccak state (see libinfnoise)
|
||||||
if (!initInfnoise(&ftdic, opts.serial, &message, !opts.raw, opts.debug)) {
|
if (!initInfnoise(&context, opts.serial, !opts.raw, opts.debug)) {
|
||||||
fprintf(stderr, "Error: %s\n", message);
|
fprintf(stderr, "Error: %s\n", context.message);
|
||||||
return 1; // ERROR
|
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
|
// endless loop
|
||||||
uint64_t totalBytesWritten = 0u;
|
uint64_t totalBytesWritten = 0u;
|
||||||
while(true) {
|
while (true) {
|
||||||
uint64_t prevTotalBytesWritten = totalBytesWritten;
|
uint8_t result[resultSize];
|
||||||
totalBytesWritten += readData_private(&ftdic, NULL, &message, &errorFlag, opts.noOutput, opts.raw, opts.outputMultiplier, opts.devRandom); // calling libinfnoise's private readData method
|
uint64_t bytesWritten = readData(&context, result, opts.raw, opts.outputMultiplier);
|
||||||
|
totalBytesWritten += bytesWritten;
|
||||||
|
|
||||||
if (errorFlag) {
|
if (context.errorFlag) {
|
||||||
fprintf(stderr, "Error: %s\n", message);
|
fprintf(stderr, "Error: %s\n", context.message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
|
if (!opts.noOutput) {
|
||||||
fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,9 @@ struct opt_struct {
|
|||||||
char *serial; // Name of selected device
|
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);
|
void startDaemon(struct opt_struct *opts);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
#include "libinfnoise_private.h"
|
#include "libinfnoise_private.h"
|
||||||
#include "libinfnoise.h"
|
|
||||||
#include "KeccakF-1600-interface.h"
|
#include "KeccakF-1600-interface.h"
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
@@ -24,19 +23,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t keccakState[KeccakPermutationSizeInBytes];
|
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();
|
prepareOutputBuffer();
|
||||||
|
|
||||||
// initialize health check
|
// initialize health check
|
||||||
if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) {
|
if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) {
|
||||||
*message="Can't initialize health checker";
|
context->message = "Can't initialize health checker";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize USB
|
// initialize USB
|
||||||
if(!initializeUSB(ftdic, message, serial)) {
|
if (!initializeUSB(&context->ftdic, &context->message, serial)) {
|
||||||
// Sometimes have to do it twice - not sure why
|
// Sometimes have to do it twice - not sure why
|
||||||
if(!initializeUSB(ftdic, message, serial)) {
|
if (!initializeUSB(&context->ftdic, &context->message, serial)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,28 +49,30 @@ bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// let healthcheck collect some data
|
// let healthcheck collect some data
|
||||||
uint32_t maxWarmupRounds = 500;
|
uint32_t maxWarmupRounds = 5000;
|
||||||
uint32_t warmupRounds = 0;
|
uint32_t warmupRounds = 0;
|
||||||
bool errorFlag = false;
|
//bool errorFlag = false;
|
||||||
while(!inmHealthCheckOkToUseData()) {
|
while (!inmHealthCheckOkToUseData()) {
|
||||||
readData_private(ftdic, NULL, message, &errorFlag, false, true, 0, false);
|
readData(context, NULL, true, 0);
|
||||||
warmupRounds++;
|
warmupRounds++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warmupRounds > maxWarmupRounds) {
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t outBuf[BUFLEN];
|
uint8_t outBuf[BUFLEN];
|
||||||
|
|
||||||
void prepareOutputBuffer() {
|
void prepareOutputBuffer() {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
// Endless loop: set SW1EN and SW2EN alternately
|
// Endless loop: set SW1EN and SW2EN alternately
|
||||||
for(i = 0u; i < BUFLEN; i++) {
|
for (i = 0u; i < BUFLEN; i++) {
|
||||||
// Alternate Ph1 and Ph2
|
// 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) {
|
uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *errorFlag) {
|
||||||
inmClearEntropyLevel();
|
inmClearEntropyLevel();
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for(i = 0u; i < BUFLEN/8u; i++) {
|
for (i = 0u; i < BUFLEN / 8u; i++) {
|
||||||
uint32_t j;
|
uint32_t j;
|
||||||
uint8_t byte = 0u;
|
uint8_t byte = 0u;
|
||||||
for(j = 0u; j < 8u; j++) {
|
for (j = 0u; j < 8u; j++) {
|
||||||
uint8_t val = inBuf[i*8u + j];
|
uint8_t val = inBuf[i * 8u + j];
|
||||||
uint8_t evenBit = (val >> COMP2) & 1u;
|
uint8_t evenBit = (val >> COMP2) & 1u;
|
||||||
uint8_t oddBit = (val >> COMP1) & 1u;
|
uint8_t oddBit = (val >> COMP1) & 1u;
|
||||||
bool even = j & 1u; // Use the even bit if j is odd
|
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;
|
byte = (byte << 1u) | bit;
|
||||||
|
|
||||||
// This is a good place to feed the bit from the INM to the health checker.
|
// 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!";
|
*message = "Health check of Infinite Noise Multiplier failed!";
|
||||||
*errorFlag = true;
|
*errorFlag = true;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -103,90 +106,26 @@ uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *erro
|
|||||||
return inmGetEntropyLevel();
|
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
|
// 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
|
// 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
|
// cryptographically secure pseudo-random data than the INM generates. If
|
||||||
// outputMultiplier is 0, we output only as many bits as we measure in entropy.
|
// 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
|
// This allows a user to generate hundreds of MiB per second if needed, for use
|
||||||
// as cryptographic keys.
|
// as cryptographic keys.
|
||||||
uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t entropy,
|
uint32_t processBytes(uint8_t *bytes, uint8_t *result, uint32_t *entropy,
|
||||||
bool raw, bool writeDevRandom, uint32_t outputMultiplier, bool noOutput,
|
uint32_t *numBits, uint32_t *bytesWritten,
|
||||||
char **message, bool *errorFlag) {
|
bool raw, uint32_t outputMultiplier) {
|
||||||
//Use the lower of the measured entropy and the provable lower bound on
|
//Use the lower of the measured entropy and the provable lower bound on
|
||||||
//average entropy.
|
//average entropy.
|
||||||
if(entropy > inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY) {
|
if (*entropy > inmExpectedEntropyPerBit * BUFLEN / INM_ACCURACY) {
|
||||||
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.
|
// In raw mode, we just output raw data from the INM.
|
||||||
if (!noOutput) {
|
if (result != NULL) {
|
||||||
if (!outputBytes(bytes, BUFLEN/8u, entropy, writeDevRandom, message)) {
|
memcpy(result, bytes, BUFLEN / 8u * sizeof(uint8_t));
|
||||||
*errorFlag = true;
|
|
||||||
return 0; // write failed
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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,
|
// 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
|
// 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
|
// gets a snapshot of the keccak state. BUFLEN must be a multiple of 64, since
|
||||||
// Keccak-1600 uses 64-bit "lanes".
|
// Keccak-1600 uses 64-bit "lanes".
|
||||||
KeccakAbsorb(keccakState, bytes, BUFLEN/64u);
|
|
||||||
if(outputMultiplier == 0u) {
|
uint8_t dataOut[1024u];
|
||||||
uint8_t dataOut[16u*8u];
|
KeccakAbsorb(keccakState, bytes, BUFLEN / 64u);
|
||||||
|
|
||||||
|
if (outputMultiplier == 0u) {
|
||||||
// Output all the bytes of entropy we have
|
// Output all the bytes of entropy we have
|
||||||
KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u);
|
KeccakExtract(keccakState, dataOut, (*entropy + 63u) / 64u);
|
||||||
if (!noOutput) {
|
if (result != NULL) {
|
||||||
if (!outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom, message)) {
|
memcpy(result, dataOut, *entropy / 8u * sizeof(uint8_t));
|
||||||
*errorFlag = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (result != NULL) {
|
|
||||||
memcpy(result, dataOut, entropy/8u * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return entropy/8u;
|
return *entropy / 8u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output 256*outputMultipler bits.
|
// Output 256*outputMultipler bits (in chunks of 1024)
|
||||||
uint32_t numBits = outputMultiplier*256u;
|
// only the first 1024 now,
|
||||||
uint32_t bytesWritten = 0u;
|
if (*numBits == 0u) {
|
||||||
uint8_t dataOut[outputMultiplier * 32u]; // ???
|
*numBits = outputMultiplier*256u;
|
||||||
|
*bytesWritten = 0u;
|
||||||
|
|
||||||
while(numBits > 0u) {
|
// Output up to 1024 bits at a time.
|
||||||
// Write up to 1024 bits at a time.
|
uint32_t bytesToWrite = 1024u / 8u;
|
||||||
uint32_t bytesToWrite = 1024u/8u;
|
if (bytesToWrite > *numBits / 8u) {
|
||||||
if(bytesToWrite > numBits/8u) {
|
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprintf(stderr, "bytesWritten: %ul\n", bytesWritten);
|
KeccakExtract(keccakState, result, bytesToWrite / 8u);
|
||||||
//fprintf(stderr, "entropy: %ul\n", entropy);
|
KeccakPermutation(keccakState);
|
||||||
|
*bytesWritten = bytesToWrite;
|
||||||
|
*numBits -= bytesToWrite * 8u;
|
||||||
|
}
|
||||||
|
return *bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
bytesWritten += bytesToWrite;
|
// Return the difference in the times as a double in microseconds.
|
||||||
numBits -= bytesToWrite*8u;
|
double diffTime(struct timespec *start, struct timespec *end) {
|
||||||
entropy -= entropyThisTime;
|
uint32_t seconds = end->tv_sec - start->tv_sec;
|
||||||
if(numBits > 0u) {
|
int32_t nanoseconds = end->tv_nsec - start->tv_nsec;
|
||||||
KeccakPermutation(keccakState);
|
return seconds * 1.0e6 + nanoseconds / 1000.0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(bytesWritten != outputMultiplier*(256u/8u)) {
|
bool isSuperUser(void) {
|
||||||
*message = "Internal error outputing bytes";
|
return (geteuid() == 0);
|
||||||
*errorFlag = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten);
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a list of all infinite noise multipliers found.
|
// Return a list of all infinite noise multipliers found.
|
||||||
bool listUSBDevices(struct ftdi_context *ftdic, char** message) {
|
devlist_node listUSBDevices(char **message) {
|
||||||
ftdi_init(ftdic);
|
struct ftdi_context ftdic;
|
||||||
|
ftdi_init(&ftdic);
|
||||||
|
|
||||||
struct ftdi_device_list *devlist;
|
struct ftdi_device_list *devlist;
|
||||||
struct ftdi_device_list *curdev;
|
struct ftdi_device_list *curdev;
|
||||||
char manufacturer[128], description[128], serial[128];
|
char manufacturer[128], description[128], serial[128];
|
||||||
int i=0;
|
int i = 0;
|
||||||
|
|
||||||
// search devices
|
// 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 (rc < 0) {
|
||||||
if (!isSuperUser()) {
|
if (!isSuperUser()) {
|
||||||
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
||||||
} else {
|
} 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++) {
|
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 (rc < 0) {
|
||||||
if (!isSuperUser()) {
|
if (!isSuperUser()) {
|
||||||
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
||||||
return false;
|
return NULL;
|
||||||
|
} else {
|
||||||
|
*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;
|
|
||||||
}
|
}
|
||||||
|
current_entry->id = i;
|
||||||
// print to stdout
|
strcpy(current_entry->serial, serial);
|
||||||
printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, 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;
|
curdev = curdev->next;
|
||||||
}
|
}
|
||||||
|
return return_list;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the Infinite Noise Multiplier USB interface.
|
// 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!";
|
*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 (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?";
|
*message = "Can't open Infinite Noise Multiplier. Try running as super user?";
|
||||||
} else {
|
} else {
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
@@ -341,7 +264,7 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) {
|
|||||||
// serial specified
|
// serial specified
|
||||||
rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial);
|
rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if(!isSuperUser()) {
|
if (!isSuperUser()) {
|
||||||
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
||||||
} else {
|
} else {
|
||||||
*message = "Can't find Infinite Noise Multiplier with given serial";
|
*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
|
// Set high baud rate
|
||||||
rc = ftdi_set_baudrate(ftdic, 30000);
|
rc = ftdi_set_baudrate(ftdic, 30000);
|
||||||
if(rc == -1) {
|
if (rc == -1) {
|
||||||
*message = "Invalid baud rate";
|
*message = "Invalid baud rate";
|
||||||
return false;
|
return false;
|
||||||
} else if(rc == -2) {
|
} else if (rc == -2) {
|
||||||
*message = "Setting baud rate failed";
|
*message = "Setting baud rate failed";
|
||||||
return false;
|
return false;
|
||||||
} else if(rc == -3) {
|
} else if (rc == -3) {
|
||||||
*message = "Infinite Noise Multiplier unavailable";
|
*message = "Infinite Noise Multiplier unavailable";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB);
|
rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB);
|
||||||
if(rc == -1) {
|
if (rc == -1) {
|
||||||
*message = "Can't enable bit-bang mode";
|
*message = "Can't enable bit-bang mode";
|
||||||
return false;
|
return false;
|
||||||
} else if(rc == -2) {
|
} else if (rc == -2) {
|
||||||
*message = "Infinite Noise Multiplier unavailable\n";
|
*message = "Infinite Noise Multiplier unavailable\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just test to see that we can write and read.
|
// Just test to see that we can write and read.
|
||||||
uint8_t buf[64u] = {0u,};
|
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";
|
*message = "USB write failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ftdi_read_data(ftdic, buf, 64) != 64) {
|
if (ftdi_read_data(ftdic, buf, 64) != 64) {
|
||||||
*message = "USB read failed";
|
*message = "USB read failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag) {
|
uint32_t readData(struct infnoise_context *context, uint8_t *result, bool raw, uint32_t outputMultiplier) {
|
||||||
return readData_private(ftdic, result, message, errorFlag, false, true, 0, false);
|
// 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) {
|
// Output up to 1024 bits at a time.
|
||||||
return readData_private(ftdic, result, message, errorFlag, false, false, outputMultiplier, false);
|
uint32_t bytesToWrite = 1024u / 8u;
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag,
|
if (bytesToWrite > context->numBits / 8u) {
|
||||||
bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom) {
|
bytesToWrite = context->numBits / 8u;
|
||||||
uint8_t inBuf[BUFLEN];
|
}
|
||||||
struct timespec start;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &start);
|
|
||||||
|
|
||||||
// write clock signal
|
KeccakExtract(keccakState, result, bytesToWrite / 8u);
|
||||||
if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) {
|
KeccakPermutation(keccakState);
|
||||||
*message = "USB write failed";
|
|
||||||
*errorFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and read 512 byte from the internal buffer (in synchronous bitbang mode)
|
context->bytesWritten += bytesToWrite;
|
||||||
if(ftdi_read_data(ftdic, inBuf, BUFLEN) != BUFLEN) {
|
context->numBits -= bytesToWrite * 8u;
|
||||||
*message = "USB read failed";
|
return 1024/8u;
|
||||||
*errorFlag = true;
|
} else { // collect new entropy
|
||||||
return 0;
|
uint8_t inBuf[BUFLEN];
|
||||||
}
|
struct timespec start;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &start);
|
||||||
|
|
||||||
struct timespec end;
|
// write clock signal
|
||||||
clock_gettime(CLOCK_REALTIME, &end);
|
if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||||
uint32_t us = diffTime(&start, &end);
|
context->message = "USB write failed";
|
||||||
if(us <= MAX_MICROSEC_FOR_SAMPLES) {
|
context->errorFlag = true;
|
||||||
uint8_t bytes[BUFLEN/8u];
|
}
|
||||||
uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag);
|
|
||||||
|
|
||||||
//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 (us <= MAX_MICROSEC_FOR_SAMPLES) {
|
||||||
if (inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) {
|
uint8_t bytes[BUFLEN / 8u];
|
||||||
uint32_t byteswritten = processBytes(bytes, result, entropy, raw, devRandom, outputMultiplier, noOutput, message, errorFlag);
|
context->entropyThisTime = extractBytes(bytes, inBuf, &context->message, &context->errorFlag);
|
||||||
return byteswritten;
|
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;
|
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
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(__FreeBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#else
|
#else
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
#include <time.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
|
// We also write this in one go to the Keccak sponge, which is at most 1600 bits
|
||||||
#define BUFLEN 512u
|
#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);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "libinfnoise.h"
|
||||||
|
|
||||||
#define INFNOISE_VENDOR_ID 0x0403
|
#define INFNOISE_VENDOR_ID 0x0403
|
||||||
#define INFNOISE_PRODUCT_ID 0x6015
|
#define INFNOISE_PRODUCT_ID 0x6015
|
||||||
@@ -37,8 +37,6 @@
|
|||||||
// All data bus bits of the FT240X are outputs, except COMP1 and COMP2
|
// All data bus bits of the FT240X are outputs, except COMP1 and COMP2
|
||||||
#define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2))
|
#define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool inmHealthCheckStart(uint8_t N, double K, bool debug);
|
bool inmHealthCheckStart(uint8_t N, double K, bool debug);
|
||||||
void inmHealthCheckStop(void);
|
void inmHealthCheckStop(void);
|
||||||
bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even);
|
bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even);
|
||||||
@@ -48,14 +46,12 @@ double inmHealthCheckEstimateEntropyPerBit(void);
|
|||||||
uint32_t inmGetEntropyLevel(void);
|
uint32_t inmGetEntropyLevel(void);
|
||||||
void inmClearEntropyLevel(void);
|
void inmClearEntropyLevel(void);
|
||||||
bool inmEntropyOnTarget(uint32_t entropy, uint32_t bits);
|
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);
|
void inmDumpStats(void);
|
||||||
|
|
||||||
extern double inmK, inmExpectedEntropyPerBit;
|
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();
|
void prepareOutputBuffer();
|
||||||
|
|
||||||
struct timespec;
|
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);
|
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);
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user