Merge pull request #12 from 13-37-org/libinfnoise
merge libinfnoise branch
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
|
||||
@@ -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;
|
||||
@@ -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 <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,7 +20,6 @@
|
||||
#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) {
|
||||
@@ -37,8 +38,8 @@ static void initOpts(struct opt_struct *opts) {
|
||||
}
|
||||
|
||||
// getopt_long(3) options descriptor
|
||||
|
||||
static struct option longopts[] = {{"raw", no_argument, NULL, 'r'},
|
||||
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'},
|
||||
@@ -51,8 +52,49 @@ static struct option longopts[] = {{"raw", no_argument, NULL, 'r'},
|
||||
{"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;
|
||||
@@ -147,7 +189,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.debug == false) {
|
||||
if (!opts.debug) {
|
||||
if (getenv("INFNOISE_DEBUG") != NULL) {
|
||||
if (!strcmp("true", getenv("INFNOISE_DEBUG"))) {
|
||||
opts.debug = true;
|
||||
@@ -155,7 +197,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (multiplierAssigned == false) {
|
||||
if (!multiplierAssigned) {
|
||||
if (getenv("INFNOISE_MULTIPLIER") != NULL) {
|
||||
int tmpOutputMult = atoi(getenv("INFNOISE_MULTIPLIER"));
|
||||
if (tmpOutputMult < 0) {
|
||||
@@ -178,21 +220,26 @@ 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);
|
||||
@@ -204,7 +251,8 @@ int main(int argc, char **argv) {
|
||||
#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
|
||||
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))) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,21 +49,23 @@ 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;
|
||||
//bool errorFlag = false;
|
||||
while (!inmHealthCheckOkToUseData()) {
|
||||
readData_private(ftdic, NULL, message, &errorFlag, false, true, 0, false);
|
||||
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;
|
||||
|
||||
@@ -103,89 +106,25 @@ 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) {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
return BUFLEN / 8u;
|
||||
}
|
||||
|
||||
@@ -196,77 +135,54 @@ 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".
|
||||
|
||||
uint8_t dataOut[1024u];
|
||||
KeccakAbsorb(keccakState, bytes, BUFLEN / 64u);
|
||||
|
||||
if (outputMultiplier == 0u) {
|
||||
uint8_t dataOut[16u*8u];
|
||||
// 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 {
|
||||
KeccakExtract(keccakState, dataOut, (*entropy + 63u) / 64u);
|
||||
if (result != NULL) {
|
||||
memcpy(result, dataOut, entropy/8u * sizeof(uint8_t));
|
||||
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.
|
||||
// Output 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];
|
||||
}
|
||||
}
|
||||
if (bytesToWrite > *numBits / 8u) {
|
||||
bytesToWrite = *numBits / 8u;
|
||||
}
|
||||
|
||||
//fprintf(stderr, "bytesWritten: %ul\n", bytesWritten);
|
||||
//fprintf(stderr, "entropy: %ul\n", entropy);
|
||||
|
||||
bytesWritten += bytesToWrite;
|
||||
numBits -= bytesToWrite*8u;
|
||||
entropy -= entropyThisTime;
|
||||
if(numBits > 0u) {
|
||||
KeccakExtract(keccakState, result, bytesToWrite / 8u);
|
||||
KeccakPermutation(keccakState);
|
||||
*bytesWritten = bytesToWrite;
|
||||
*numBits -= bytesToWrite * 8u;
|
||||
}
|
||||
return *bytesWritten;
|
||||
}
|
||||
if(bytesWritten != outputMultiplier*(256u/8u)) {
|
||||
*message = "Internal error outputing bytes";
|
||||
*errorFlag = true;
|
||||
return 0;
|
||||
|
||||
// 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;
|
||||
}
|
||||
//fprintf(stderr, "bytesWritten_end: %ul\n", bytesWritten);
|
||||
return bytesWritten;
|
||||
|
||||
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;
|
||||
@@ -274,34 +190,41 @@ bool listUSBDevices(struct ftdi_context *ftdic, char** message) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -385,87 +308,59 @@ bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) {
|
||||
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!
|
||||
|
||||
// Output up to 1024 bits at a time.
|
||||
uint32_t bytesToWrite = 1024u / 8u;
|
||||
|
||||
if (bytesToWrite > context->numBits / 8u) {
|
||||
bytesToWrite = context->numBits / 8u;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
KeccakExtract(keccakState, result, bytesToWrite / 8u);
|
||||
KeccakPermutation(keccakState);
|
||||
|
||||
uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag,
|
||||
bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom) {
|
||||
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);
|
||||
|
||||
// write clock signal
|
||||
if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||
*message = "USB write failed";
|
||||
*errorFlag = true;
|
||||
if (ftdi_write_data(&context->ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||
context->message = "USB write failed";
|
||||
context->errorFlag = true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
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);
|
||||
|
||||
if (us <= MAX_MICROSEC_FOR_SAMPLES) {
|
||||
uint8_t bytes[BUFLEN / 8u];
|
||||
uint32_t entropy = extractBytes(bytes, inBuf, message, errorFlag);
|
||||
|
||||
//fprintf(stderr, "ERROR1: %ul\n", entropy);
|
||||
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,9 +46,7 @@ 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;
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user