Merge pull request #65 from dirkx/master
Minor tweaks for FreeBSD (and simplify for OSX)
This commit is contained in:
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "software/tests/test_helper/bats-support"]
|
||||
path = software/tests/test_helper/bats-support
|
||||
url = https://github.com/ztombol/bats-support
|
||||
[submodule "software/tests/test_helper/bats-assert"]
|
||||
path = software/tests/test_helper/bats-assert
|
||||
url = https://github.com/ztombol/bats-assert
|
||||
10
software/.gitignore
vendored
10
software/.gitignore
vendored
@@ -1 +1,9 @@
|
||||
./infnoise
|
||||
infnoise
|
||||
KeccakF-1600-reference.o
|
||||
daemon.o
|
||||
healthcheck.o
|
||||
infnoise
|
||||
infnoise.o
|
||||
libinfnoise.a
|
||||
libinfnoise.o
|
||||
libinfnoise.so
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
GIT_VERSION := $(shell git --no-pager describe --tags --always)
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD)
|
||||
GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only))
|
||||
|
||||
PREFIX = $(DESTDIR)/usr/local
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -I Keccak -I /usr/include/libftdi1 \
|
||||
-DGIT_VERSION=\"$(GIT_VERSION)\"\
|
||||
-DGIT_COMMIT=\"$(GIT_COMMIT)\"\
|
||||
-DGIT_DATE=\"$(GIT_DATE)\"\
|
||||
-DBUILD_DATE=\"$(BUILD_DATE)\"
|
||||
|
||||
FOUND = $(shell /sbin/ldconfig -p | grep --silent libftdi.so && echo found)
|
||||
ifeq ($(FOUND), found)
|
||||
FTDI= -lftdi
|
||||
else
|
||||
FTDI= -lftdi1
|
||||
endif
|
||||
|
||||
all: infnoise
|
||||
|
||||
infnoise: infnoise.c infnoise.h healthcheck.c writeentropy.c daemon.c Keccak/KeccakF-1600-reference.c Keccak/brg_endian.h
|
||||
$(CC) $(CFLAGS) -o infnoise infnoise.c healthcheck.c writeentropy.c daemon.c Keccak/KeccakF-1600-reference.c $(FTDI) -lm -lrt
|
||||
|
||||
clean:
|
||||
$(RM) infnoise
|
||||
|
||||
install:
|
||||
install -d $(PREFIX)/sbin
|
||||
install -m 0755 infnoise $(PREFIX)/sbin/
|
||||
install -d $(PREFIX)/lib/udev/rules.d/
|
||||
install -m 0644 init_scripts/75-infnoise.rules $(PREFIX)/lib/udev/rules.d/
|
||||
install -d $(PREFIX)/lib/systemd/system
|
||||
install -m 0644 init_scripts/infnoise.service $(PREFIX)/lib/systemd/system
|
||||
|
||||
postinstall:
|
||||
systemctl restart systemd-udevd
|
||||
systemctl enable infnoise
|
||||
65
software/Makefile.freebsd
Normal file
65
software/Makefile.freebsd
Normal file
@@ -0,0 +1,65 @@
|
||||
GIT_VERSION := $(shell git --no-pager describe --tags --always)
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD)
|
||||
GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only))
|
||||
|
||||
PREFIX = $(DESTDIR)/usr/local
|
||||
|
||||
# Against: libftdi1 from ports/pkg
|
||||
#
|
||||
FTDILOCI = /usr/local/include/libftdi1
|
||||
FTDILOCL = /usr/local/lib
|
||||
FTDI= -lftdi1
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I Keccak -I $(FTDILOCI) \
|
||||
-DGIT_VERSION=\"$(GIT_VERSION)\"\
|
||||
-DGIT_COMMIT=\"$(GIT_COMMIT)\"\
|
||||
-DGIT_DATE=\"$(GIT_DATE)\"\
|
||||
|
||||
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)
|
||||
|
||||
%.o: %.c infnoise.h libinfnoise.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
KeccakF-1600-reference.o: Keccak/KeccakF-1600-reference.c Keccak/KeccakF-1600-interface.h Keccak/brg_endian.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
# static lib compiled into infnoise binary
|
||||
libinfnoise.o: libinfnoise.c libinfnoise.h libinfnoise_private.h healthcheck.c
|
||||
$(CC) $(CFLAGS) -c libinfnoise.c
|
||||
|
||||
libinfnoise.a: libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
ar rcs libinfnoise.a libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
ranlib libinfnoise.a
|
||||
|
||||
# shared lib
|
||||
libinfnoise.so: libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
$(CC) $(CFLAGS) -fvisibility=hidden -o libinfnoise.so libinfnoise.o healthcheck.o KeccakF-1600-reference.o -L $(FTDILOCL) -Wl $(FTDI) -lm -shared
|
||||
|
||||
libs: libinfnoise.a
|
||||
|
||||
clean:
|
||||
$(RM) -f infnoise *.o *.a *.gch *.so libinfnoise-example
|
||||
|
||||
install-lib: libinfnoise.so
|
||||
install -d $(PREFIX)/include
|
||||
install -m 0644 libinfnoise.h $(PREFIX)/include
|
||||
install -d $(PREFIX)/lib
|
||||
install -m 0644 libinfnoise.so $(PREFIX)/lib
|
||||
ldconfig $(PREFIX)/lib
|
||||
|
||||
install: infnoise
|
||||
install -d $(PREFIX)/sbin
|
||||
install -m 0755 infnoise $(PREFIX)/sbin/
|
||||
install -d $(PREFIX)/lib/udev/rules.d/
|
||||
install -m 0644 init_scripts/75-infnoise.rules $(PREFIX)/lib/udev/rules.d/
|
||||
install -d $(PREFIX)/lib/systemd/system
|
||||
install -m 0644 init_scripts/infnoise.service $(PREFIX)/lib/systemd/system
|
||||
|
||||
postinstall:
|
||||
systemctl restart systemd-udevd
|
||||
systemctl enable infnoise
|
||||
65
software/Makefile.linux
Normal file
65
software/Makefile.linux
Normal file
@@ -0,0 +1,65 @@
|
||||
GIT_VERSION := $(shell git --no-pager describe --tags --always)
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD)
|
||||
GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only))
|
||||
|
||||
PREFIX = $(DESTDIR)/usr/local
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I Keccak -I /usr/include/libftdi1 \
|
||||
-DGIT_VERSION=\"$(GIT_VERSION)\"\
|
||||
-DGIT_COMMIT=\"$(GIT_COMMIT)\"\
|
||||
-DGIT_DATE=\"$(GIT_DATE)\"\
|
||||
-DLINUX
|
||||
|
||||
FOUND = $(shell /sbin/ldconfig -p | grep --silent libftdi.so && echo found)
|
||||
ifeq ($(FOUND), found)
|
||||
FTDI= -lftdi
|
||||
else
|
||||
FTDI= -lftdi1
|
||||
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
|
||||
|
||||
%.o: %.c infnoise.h libinfnoise.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
KeccakF-1600-reference.o: Keccak/KeccakF-1600-reference.c Keccak/KeccakF-1600-interface.h Keccak/brg_endian.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
# static lib compiled into infnoise binary
|
||||
libinfnoise.o: libinfnoise.c libinfnoise.h libinfnoise_private.h healthcheck.c
|
||||
$(CC) $(CFLAGS) -c libinfnoise.c
|
||||
|
||||
libinfnoise.a: libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o
|
||||
ar rcs libinfnoise.a libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o
|
||||
ranlib libinfnoise.a
|
||||
|
||||
# shared lib
|
||||
libinfnoise.so: libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o
|
||||
$(CC) $(CFLAGS) -fvisibility=hidden -o libinfnoise.so libinfnoise.o healthcheck.o KeccakF-1600-reference.o writeentropy.o -Wl,--version-script=libinfnoise.version $(FTDI) -lm -shared
|
||||
|
||||
libs: libinfnoise.a
|
||||
|
||||
clean:
|
||||
$(RM) infnoise *.o *.a *.gch *.so libinfnoise-example
|
||||
|
||||
install-lib: libinfnoise.so
|
||||
install -d $(PREFIX)/include
|
||||
install -m 0644 libinfnoise.h $(PREFIX)/include
|
||||
install -d $(PREFIX)/lib
|
||||
install -m 0644 libinfnoise.so $(PREFIX)/lib
|
||||
ldconfig $(PREFIX)/lib
|
||||
|
||||
install: infnoise
|
||||
install -d $(PREFIX)/sbin
|
||||
install -m 0755 infnoise $(PREFIX)/sbin/
|
||||
install -d $(PREFIX)/lib/udev/rules.d/
|
||||
install -m 0644 init_scripts/75-infnoise.rules $(PREFIX)/lib/udev/rules.d/
|
||||
install -d $(PREFIX)/lib/systemd/system
|
||||
install -m 0644 init_scripts/infnoise.service $(PREFIX)/lib/systemd/system
|
||||
|
||||
postinstall:
|
||||
systemctl restart systemd-udevd
|
||||
systemctl enable infnoise
|
||||
66
software/Makefile.macos
Normal file
66
software/Makefile.macos
Normal file
@@ -0,0 +1,66 @@
|
||||
GIT_VERSION := $(shell git --no-pager describe --tags --always)
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD)
|
||||
GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only))
|
||||
|
||||
PREFIX = $(DESTDIR)/usr/local
|
||||
|
||||
# Against 'libftdi0' from MacOS X ports or brew
|
||||
#
|
||||
FTDILOCI = /opt/local/include
|
||||
FTDILOCL = /opt/local/lib
|
||||
FTDI= -lftdi
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I Keccak -I $(FTDILOCI) \
|
||||
-DGIT_VERSION=\"$(GIT_VERSION)\"\
|
||||
-DGIT_COMMIT=\"$(GIT_COMMIT)\"\
|
||||
-DGIT_DATE=\"$(GIT_DATE)\"\
|
||||
|
||||
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
|
||||
|
||||
%.o: %.c infnoise.h libinfnoise.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
KeccakF-1600-reference.o: Keccak/KeccakF-1600-reference.c Keccak/KeccakF-1600-interface.h Keccak/brg_endian.h
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
# static lib compiled into infnoise binary
|
||||
libinfnoise.o: libinfnoise.c libinfnoise.h libinfnoise_private.h healthcheck.c
|
||||
$(CC) $(CFLAGS) -c libinfnoise.c
|
||||
|
||||
libinfnoise.a: libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
|
||||
ar rcs libinfnoise.a libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
ranlib libinfnoise.a
|
||||
|
||||
# shared lib
|
||||
libinfnoise.so: libinfnoise.o healthcheck.o KeccakF-1600-reference.o
|
||||
$(CC) $(CFLAGS) -fvisibility=hidden -o libinfnoise.so libinfnoise.o healthcheck.o KeccakF-1600-reference.o -L $(FTDILOCL) -Wl $(FTDI) -lm -shared
|
||||
|
||||
libs: libinfnoise.a
|
||||
|
||||
clean:
|
||||
$(RM) -f infnoise *.o *.a *.gch *.so libinfnoise-example
|
||||
|
||||
install-lib: libinfnoise.so
|
||||
install -d $(PREFIX)/include
|
||||
install -m 0644 libinfnoise.h $(PREFIX)/include
|
||||
install -d $(PREFIX)/lib
|
||||
install -m 0644 libinfnoise.so $(PREFIX)/lib
|
||||
ldconfig $(PREFIX)/lib
|
||||
|
||||
install: infnoise
|
||||
install -d $(PREFIX)/sbin
|
||||
install -m 0755 infnoise $(PREFIX)/sbin/
|
||||
install -d $(PREFIX)/lib/udev/rules.d/
|
||||
install -m 0644 init_scripts/75-infnoise.rules $(PREFIX)/lib/udev/rules.d/
|
||||
install -d $(PREFIX)/lib/systemd/system
|
||||
install -m 0644 init_scripts/infnoise.service $(PREFIX)/lib/systemd/system
|
||||
|
||||
postinstall:
|
||||
systemctl restart systemd-udevd
|
||||
systemctl enable infnoise
|
||||
@@ -33,7 +33,7 @@ Repositories for Ubuntu, Debian and Raspbian are also available. To add them fol
|
||||
# GPG2:
|
||||
$ gpg2 --import-options import-show --dry-run --import < 13-37.org-code.asc
|
||||
|
||||
$ sudo apt-key add 13-37.org-code.gpg
|
||||
$ sudo apt-key add 13-37.org-code.asc
|
||||
|
||||
Available for Ubuntu and Debian (x86, x64 and armhf):
|
||||
|
||||
|
||||
@@ -15,9 +15,11 @@ build() {
|
||||
|
||||
package() {
|
||||
install -Dvm755 "${srcdir}/infnoise/software/infnoise" "${pkgdir}/usr/bin/infnoise"
|
||||
install -Dvm644 "${srcdir}/infnoise/software/libinfnoise.a" "${pkgdir}/usr/lib/libinfnoise.a"
|
||||
install -Dvm755 "${srcdir}/infnoise/software/libinfnoise.so" "${pkgdir}/usr/lib/libinfnoise.so"
|
||||
install -Dvm644 "${srcdir}/infnoise/software/init_scripts/75-infnoise.rules" "${pkgdir}/etc/udev/rules.d/75-infnoise.rules"
|
||||
install -Dvm644 "${srcdir}/infnoise/software/init_scripts/infnoise.conf.systemd" "${pkgdir}/etc/infnoise.conf"
|
||||
install -Dvm644 "${srcdir}/infnoise/software/init_scripts/infnoise.service.bin" "${pkgdir}/lib/systemd/system/infnoise.service"
|
||||
install -Dvm644 "${srcdir}/infnoise/software/init_scripts/infnoise.service.bin" "${pkgdir}/usr/lib/systemd/system/infnoise.service"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ and can create packages of the following types:
|
||||
- RPM (CentOS, Fedora)
|
||||
- ArchLinux
|
||||
|
||||
The packages get signed afterwards and made available as Github releases
|
||||
The packages are signed and made available as Github releases
|
||||
and via the apt repository described in software/README.
|
||||
|
||||
During the build the GitHub release and version information are compiled into the binary.
|
||||
|
||||
@@ -3,29 +3,49 @@
|
||||
VERSION=`git --no-pager describe --tags --always | cut -d'-' -f1`
|
||||
PKGREL=`git --no-pager describe --tags --always | cut -d'-' -f2`
|
||||
|
||||
GITREPO=`git config --get remote.origin.url`
|
||||
|
||||
if [ $VERSION == $PKGREL ]; then # this is a release
|
||||
PKGREL=0
|
||||
fi
|
||||
|
||||
|
||||
SIGNPACKAGE=true
|
||||
while test $# -gt 0
|
||||
do
|
||||
case "$1" in
|
||||
--notsigned) SIGNPACKAGE=false
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
|
||||
# x86_64
|
||||
mkdir -p x86_64
|
||||
cd x86_64
|
||||
|
||||
cp ../build-scripts/PKGBUILD.arch PKGBUILD
|
||||
cp ../build-scripts/INSTALL.arch INSTALL
|
||||
echo "pkgver=$VERSION" >> PKGBUILD
|
||||
echo "pkgrel=$PKGREL" >> PKGBUILD
|
||||
cp ../PKGBUILD.arch PKGBUILD
|
||||
cp ../INSTALL.arch INSTALL
|
||||
sed -i "s|.*source.*=.*(.*).*|source=('git+$GITREPO')|g" PKGBUILD
|
||||
echo "pkgver=$VERSION.$PKGREL" >> PKGBUILD
|
||||
echo "pkgrel=1" >> PKGBUILD
|
||||
echo "arch=('x86_64')" >> PKGBUILD
|
||||
ls -lah
|
||||
makepkg -f --sign --key 975DC25C4E730A3C
|
||||
if [ "$SIGNPACKAGE" = true ]; then
|
||||
makepkg -f --sign --key 975DC25C4E730A3C
|
||||
else
|
||||
makepkg -f
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# x86_64
|
||||
# x86
|
||||
mkdir -p x86
|
||||
cd x86
|
||||
cp ../build-scripts/PKGBUILD.arch PKGBUILD
|
||||
cp ../build-scripts/INSTALL.arch INSTALL
|
||||
echo "pkgver=$VERSION" >> PKGBUILD
|
||||
echo "pkgrel=$PKGREL" >> PKGBUILD
|
||||
|
||||
cp ../PKGBUILD.arch PKGBUILD
|
||||
cp ../INSTALL.arch INSTALL
|
||||
echo "pkgver=$VERSION.$PKGREL" >> PKGBUILD
|
||||
echo "pkgrel=1" >> PKGBUILD
|
||||
echo "arch=('i686')" >> PKGBUILD
|
||||
makechrootpkg -r /x86 -U jenkins -- --sign --key 975DC25C4E730A3C
|
||||
|
||||
@@ -59,3 +59,24 @@ echo "Architecture: $ARCH" >> build/DEBIAN/control
|
||||
dpkg -b build/ infnoise-tools_${VERSION}_${ARCH}.deb
|
||||
|
||||
rm -rf build
|
||||
cd ..
|
||||
|
||||
### build libinfnoise ###
|
||||
rm -rf build
|
||||
|
||||
mkdir -p build/usr/lib
|
||||
mkdir -p build/usr/include
|
||||
|
||||
make libinfnoise.so
|
||||
|
||||
cp libinfnoise.so build/usr/lib/
|
||||
cp libinfnoise.h build/usr/include
|
||||
|
||||
mkdir -p build/DEBIAN
|
||||
cp build-scripts/control.debian.lib build/DEBIAN/control
|
||||
echo "Version: $VERSION" >> build/DEBIAN/control
|
||||
echo "Architecture: $ARCH" >> build/DEBIAN/control
|
||||
|
||||
dpkg -b build/ libinfnoise_${VERSION}_${ARCH}.deb
|
||||
|
||||
rm -rf build
|
||||
|
||||
8
software/build-scripts/control.debian.lib
Normal file
8
software/build-scripts/control.debian.lib
Normal file
@@ -0,0 +1,8 @@
|
||||
Package: libinfnoise
|
||||
Essential: no
|
||||
Section: security
|
||||
Depends: libftdi1
|
||||
Priority: optional
|
||||
Maintainer: Manuel Domke
|
||||
Installed-Size: 12K
|
||||
Description: Infinite Noise TRNG library
|
||||
@@ -48,6 +48,3 @@ void startDaemon(struct opt_struct* opts) {
|
||||
// Child
|
||||
}
|
||||
|
||||
bool isSuperUser(void) {
|
||||
return (geteuid() == 0);
|
||||
}
|
||||
|
||||
26
software/examples/README.md
Normal file
26
software/examples/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Usage examples for Infinite Noise
|
||||
|
||||
## Integrate the binary to python
|
||||
|
||||
See the python examples `serial-numbers.py` and `randomserver.py` to see how you could integrate it with python.
|
||||
|
||||
#### serial-numbers.py
|
||||
An extended version of this script was used to generate the serial numbers of all Infinite Noise's made by 13-37.org. The numbers generated by this simpler one are not guaranteed to be unique, thats why I use the UNIQUE constraint of a database when storing them.
|
||||
|
||||
This simple version just prints the serials to stdout. Call like this:
|
||||
|
||||
$ ./serial-numbers.py -c 3 -l 8
|
||||
0A8BBA15
|
||||
0341F762
|
||||
813DC0BD
|
||||
|
||||
#### randomserver.py
|
||||
|
||||
A simple webserver based on the web.py framework to serve random data via a REST interface. An example is hosted at https://rng.13-37.org (running on a Raspberry Pi in Amsterdam, thanks to pcextreme.nl!)
|
||||
|
||||
It has only two resources: `/get` and `/status`.
|
||||
|
||||
## libinfnoise
|
||||
|
||||
TODO
|
||||
|
||||
26
software/examples/libinfnoise/Makefile
Normal file
26
software/examples/libinfnoise/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
GIT_VERSION := $(shell git --no-pager describe --tags --always)
|
||||
GIT_COMMIT := $(shell git rev-parse --verify HEAD)
|
||||
GIT_DATE := $(firstword $(shell git --no-pager show --date=iso-strict --format="%ad" --name-only))
|
||||
|
||||
PREFIX = $(DESTDIR)/usr/local
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c99 -O3 -fPIC -I Keccak -I /usr/include/libftdi1 \
|
||||
-DGIT_VERSION=\"$(GIT_VERSION)\"\
|
||||
-DGIT_COMMIT=\"$(GIT_COMMIT)\"\
|
||||
-DGIT_DATE=\"$(GIT_DATE)\"\
|
||||
|
||||
LDFLAGS= -shared
|
||||
|
||||
FTDI := $(shell libftdi-config --libs)
|
||||
|
||||
all: libinfnoise-example libinfnoise-example-raw
|
||||
|
||||
libinfnoise-example: example.c
|
||||
$(CC) $(CFLAGS) -o libinfnoise-example example.c $(FTDI) -lm -lrt -linfnoise
|
||||
|
||||
libinfnoise-example-raw: example.c
|
||||
$(CC) $(CFLAGS) -o libinfnoise-example-raw example-raw.c $(FTDI) -lm -lrt -linfnoise
|
||||
|
||||
clean:
|
||||
$(RM) libinfnoise-example* *.o
|
||||
|
||||
46
software/examples/libinfnoise/example-raw.c
Normal file
46
software/examples/libinfnoise/example-raw.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
57
software/examples/libinfnoise/example.c
Normal file
57
software/examples/libinfnoise/example.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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 = 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;
|
||||
|
||||
// initialize hardware and health monitor
|
||||
struct ftdi_context ftdic;
|
||||
if (!initInfnoise(&ftdic, serial, &message, true, debug)) {
|
||||
fputs(message, stderr);
|
||||
return 1; // ERROR
|
||||
}
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
resultSize = multiplier*32u;
|
||||
}
|
||||
|
||||
// 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(&ftdic, result, &message, &errorFlag, multiplier);
|
||||
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 as many bytes
|
||||
fwrite(result, 1, bytesWritten, stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
94
software/examples/random-server.py
Executable file
94
software/examples/random-server.py
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import shlex
|
||||
import subprocess
|
||||
from threading import Thread
|
||||
import time
|
||||
import web
|
||||
|
||||
urls = (
|
||||
'/', 'help',
|
||||
'/get', 'GetRandomData',
|
||||
# '/reg', 'Register',
|
||||
'/status', 'GetPoolStatus'
|
||||
)
|
||||
|
||||
RESPONSE_SIZE=8192
|
||||
|
||||
MIN_POOL_SIZE=1 # in MB
|
||||
MAX_POOL_SIZE=32 # in MB
|
||||
|
||||
class help:
|
||||
def GET(self):
|
||||
message= "<html><head>"
|
||||
message+= "<title>Infinite Noise webservice</title></head>"
|
||||
message+= "<body><h1>Usage:</h1><table border=1>"
|
||||
message+= "<tr><td><b>request</b></td><td><b>help</b></td></tr>"
|
||||
message+= "<tr><td>/status</td><td>show current buffer status</td></tr>"
|
||||
message+= "<tr><td>/get</td><td>get " + str(RESPONSE_SIZE) + "bytes (binary format)</td></tr>"
|
||||
# print "<td><tr>/reg</tr><tr>todo</tr></td>"
|
||||
message+= "</table>"
|
||||
message+= "</body></html>"
|
||||
return message
|
||||
|
||||
class GetRandomData:
|
||||
def GET(self):
|
||||
return POOL.getData()
|
||||
|
||||
class GetPoolStatus:
|
||||
def GET(self):
|
||||
return POOL.getStatus()
|
||||
|
||||
class RandPool(object):
|
||||
minPoolSize = (MIN_POOL_SIZE * 1024 * 1024) / RESPONSE_SIZE
|
||||
maxPoolSize = (MAX_POOL_SIZE * 1024 * 1024) / RESPONSE_SIZE
|
||||
poolFillmark = -1
|
||||
randomPool = list()
|
||||
process = None
|
||||
do_run = True
|
||||
|
||||
def __init__(self):
|
||||
command = "sudo /usr/sbin/infnoise --multiplier 10"
|
||||
self.process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
|
||||
for i in range(0, self.minPoolSize):
|
||||
self.randomPool.append(self.process.stdout.read(RESPONSE_SIZE))
|
||||
self.poolFillmark+= 1
|
||||
thread2 = Thread(target=self.monitorPool)
|
||||
thread2.start()
|
||||
|
||||
def monitorPool(self):
|
||||
while getattr(self, "do_run", True):
|
||||
if self.poolFillmark < self.maxPoolSize: # keep pool at 100%
|
||||
print(str(self.poolFillmark)+ "/" + str(self.maxPoolSize))
|
||||
self.__refill_pool__()
|
||||
time.sleep(1)
|
||||
print("Stopping as you wish.")
|
||||
self.process.kill()
|
||||
|
||||
def __refill_pool__(self):
|
||||
print("refilling pool - current level: " + str(self.poolFillmark))
|
||||
for i in range(self.poolFillmark, self.maxPoolSize):
|
||||
self.randomPool.append(self.process.stdout.read(RESPONSE_SIZE))
|
||||
self.poolFillmark += 1
|
||||
self.randomPool.reverse()
|
||||
print("refilled pool - new level: " + str(self.poolFillmark))
|
||||
|
||||
def getData(self):
|
||||
if self.poolFillmark <= 0:
|
||||
web.ctx.status = '503 Service currently unavailable - Out of entropy error'
|
||||
return "0"
|
||||
value = self.randomPool[self.poolFillmark]
|
||||
self.randomPool[self.poolFillmark] = None
|
||||
self.poolFillmark -= 1
|
||||
return value
|
||||
|
||||
def getStatus(self):
|
||||
return str(self.poolFillmark) + "/" + str(self.maxPoolSize)
|
||||
|
||||
POOL = RandPool()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = web.application(urls, globals())
|
||||
app.run()
|
||||
POOL.do_run = False
|
||||
|
||||
36
software/examples/serial-numbers.py
Executable file
36
software/examples/serial-numbers.py
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Generate random serial numbers')
|
||||
parser.add_argument('-l', dest='length', action='store', default=8,
|
||||
help='length of each serial number', type=int)
|
||||
parser.add_argument('-c', dest='count', action='store', default=10,
|
||||
help='length of each serial number', type=int)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args() # parse arguments
|
||||
unique_serials_generated = 0 # counter for serials inserted successfully.
|
||||
while unique_serials_generated < args.count: # loop until enough unique serials are created (because some could fail)
|
||||
serials_list = readHexStrings(args.count - unique_serials_generated, args.length) # read $count hex-strings of fixed $length
|
||||
for serial in serials_list:
|
||||
if ("\n" in serial) or (" " in serial):
|
||||
continue # dont use serials with newlines or spaces
|
||||
unique_serials_generated += 1 # counter for serials
|
||||
serial = serial.upper()
|
||||
print(serial)
|
||||
|
||||
def readHexStrings(count, length):
|
||||
list = []
|
||||
infnoise_proc = subprocess.Popen(["infnoise"], stdout=subprocess.PIPE) # run infinite noise driver and
|
||||
bin2hex_proc = subprocess.Popen(["infnoise-bin2hex"], stdin=infnoise_proc.stdout, # feed its stdout to the bin2hex utility,
|
||||
stdout=subprocess.PIPE) # you could also skip this and do the bin2hex conversion in python
|
||||
while len(list) < count and infnoise_proc.poll() == None:
|
||||
list.append(bin2hex_proc.stdout.read(length))
|
||||
infnoise_proc.terminate()
|
||||
bin2hex_proc.terminate()
|
||||
return list
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -24,7 +24,7 @@ confirmed.
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "infnoise.h"
|
||||
#include "libinfnoise_private.h"
|
||||
|
||||
#define INM_MIN_DATA 80000u
|
||||
#define INM_MIN_SAMPLE_SIZE 100u
|
||||
@@ -91,11 +91,11 @@ static void resetStats(void) {
|
||||
// Initialize the health check. N is the number of bits used to predict the next bit.
|
||||
// At least 8 bits must be used, and no more than 30. In general, we should use bits
|
||||
// large enough so that INM output will be uncorrelated with bits N samples back in time.
|
||||
bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts) {
|
||||
bool inmHealthCheckStart(uint8_t N, double K, bool debug) {
|
||||
if(N < 1u || N > 30u) {
|
||||
return false;
|
||||
}
|
||||
inmDebug = opts->debug;
|
||||
inmDebug = debug;
|
||||
inmNumBitsOfEntropy = 0u;
|
||||
inmCurrentProbability = 1.0;
|
||||
inmK = K;
|
||||
@@ -297,6 +297,7 @@ bool inmEntropyOnTarget(uint32_t entropy, uint32_t numBits) {
|
||||
}
|
||||
|
||||
#ifdef TEST_HEALTHCHECK
|
||||
#include "infnoise.h"
|
||||
|
||||
// Compare the ability to predict with 1 fewer bits and see how much less accurate we are.
|
||||
static void checkLSBStatsForNBits(uint8_t N) {
|
||||
@@ -375,7 +376,7 @@ int main() {
|
||||
//double K = sqrt(2.0);
|
||||
double K = 1.82;
|
||||
uint8_t N = 16u;
|
||||
inmHealthCheckStart(N, K, &opts);
|
||||
inmHealthCheckStart(N, K, false);
|
||||
srand(time(NULL));
|
||||
double A = (double)rand()/RAND_MAX; // Simulating INM
|
||||
double noiseAmplitude = 1.0/(1u << 10);
|
||||
|
||||
@@ -3,255 +3,37 @@
|
||||
// Required to include clock_gettime
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#define INFNOISE_VENDOR_ID 0x0403
|
||||
#define INFNOISE_PRODUCT_ID 0x6015
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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 <ftdi.h>
|
||||
#include <sys/types.h>
|
||||
#include <ftdi.h> // requires <sys/types.h>
|
||||
#include <getopt.h>
|
||||
#include "infnoise.h"
|
||||
#include "libinfnoise.h"
|
||||
#include "libinfnoise_private.h"
|
||||
#include "KeccakF-1600-interface.h"
|
||||
|
||||
// Extract the INM output from the data received. Basically, either COMP1 or COMP2
|
||||
// changes, not both, so alternate reading bits from them. We get 1 INM bit of output
|
||||
// per byte read. Feed bits from the INM to the health checker. Return the expected
|
||||
// bits of entropy.
|
||||
static uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf) {
|
||||
inmClearEntropyLevel();
|
||||
uint32_t i;
|
||||
for(i = 0u; i < BUFLEN/8u; i++) {
|
||||
uint32_t j;
|
||||
uint8_t byte = 0u;
|
||||
for(j = 0u; j < 8u; j++) {
|
||||
uint8_t val = inBuf[i*8u + j];
|
||||
uint8_t evenBit = (val >> COMP2) & 1u;
|
||||
uint8_t oddBit = (val >> COMP1) & 1u;
|
||||
bool even = j & 1u; // Use the even bit if j is odd
|
||||
uint8_t bit = even? evenBit : oddBit;
|
||||
byte = (byte << 1u) | bit;
|
||||
// This is a good place to feed the bit from the INM to the health checker.
|
||||
if(!inmHealthCheckAddBit(evenBit, oddBit, even)) {
|
||||
fputs("Health check of Infinite Noise Multiplier failed!\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
bytes[i] = byte;
|
||||
}
|
||||
return inmGetEntropyLevel();
|
||||
}
|
||||
|
||||
// Write the bytes to either stdout, or /dev/random.
|
||||
static void outputBytes(uint8_t *bytes, uint32_t length, uint32_t entropy, struct opt_struct *opts) {
|
||||
if(!opts->devRandom) {
|
||||
if(fwrite(bytes, 1, length, stdout) != length) {
|
||||
fputs("Unable to write output from Infinite Noise Multiplier\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
inmWaitForPoolToHaveRoom();
|
||||
inmWriteEntropyToPool(bytes, length, entropy);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 cryptogrpahic keys.
|
||||
static uint32_t processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entropy, struct opt_struct* opts) {
|
||||
//Use the lower of the measured entropy and the provable lower bound on
|
||||
//average entropy.
|
||||
if(entropy > inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY) {
|
||||
entropy = inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY;
|
||||
}
|
||||
if(opts->raw) {
|
||||
// In raw mode, we just output raw data from the INM.
|
||||
outputBytes(bytes, BUFLEN/8u, entropy, opts);
|
||||
return BUFLEN/8u;
|
||||
}
|
||||
// Note that BUFLEN has to be less than 1600 by enough to make the sponge secure,
|
||||
// since outputing all 1600 bits would tell an attacker the Keccak state, allowing
|
||||
// him to predict any further output, when outputMultiplier > 1, until the next call
|
||||
// to processBytes. All 512 bits are absorbed before sqeezing data out to insure that
|
||||
// we instantly recover (reseed) from a state compromise, which is when an attacker
|
||||
// gets a snapshot of the keccak state. BUFLEN must be a multiple of 64, since
|
||||
// Keccak-1600 uses 64-bit "lanes".
|
||||
KeccakAbsorb(keccakState, bytes, BUFLEN/64u);
|
||||
uint8_t dataOut[16u*8u];
|
||||
if(opts->outputMultiplier == 0u) {
|
||||
// Output all the bytes of entropy we have
|
||||
KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u);
|
||||
outputBytes(dataOut, entropy/8u, entropy & 0x7u, opts);
|
||||
return entropy/8u;
|
||||
}
|
||||
|
||||
// Output 256*outputMultipler bytes.
|
||||
uint32_t numBits = opts->outputMultiplier*256u;
|
||||
uint32_t bytesWritten = 0u;
|
||||
while(numBits > 0u) {
|
||||
// Write up to 1024 bits at a time.
|
||||
uint32_t bytesToWrite = 1024u/8u;
|
||||
if(bytesToWrite > numBits/8u) {
|
||||
bytesToWrite = numBits/8u;
|
||||
}
|
||||
KeccakExtract(keccakState, dataOut, bytesToWrite/8u);
|
||||
uint32_t entropyThisTime = entropy;
|
||||
if(entropyThisTime > 8u*bytesToWrite) {
|
||||
entropyThisTime = 8u*bytesToWrite;
|
||||
}
|
||||
outputBytes(dataOut, bytesToWrite, entropyThisTime, opts);
|
||||
bytesWritten += bytesToWrite;
|
||||
numBits -= bytesToWrite*8u;
|
||||
entropy -= entropyThisTime;
|
||||
if(numBits > 0u) {
|
||||
KeccakPermutation(keccakState);
|
||||
}
|
||||
}
|
||||
if(bytesWritten != opts->outputMultiplier*(256u/8u)) {
|
||||
fprintf(stderr, "Internal error outputing bytes\n");
|
||||
exit(1);
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
// Return a list of all infinite noise multipliers found.
|
||||
static bool listUSBDevices(struct ftdi_context *ftdic) {
|
||||
ftdi_init(ftdic);
|
||||
|
||||
struct ftdi_device_list *devlist;
|
||||
struct ftdi_device_list *curdev;
|
||||
char manufacturer[128], description[128], serial[128];
|
||||
int i=0;
|
||||
|
||||
// search devices
|
||||
int rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID);
|
||||
|
||||
if (rc < 0) {
|
||||
if (!isSuperUser()) {
|
||||
fprintf(stderr, "Can't find Infinite Noise Multiplier. Try running as super user?\n");
|
||||
} else {
|
||||
fprintf(stderr, "Can't find Infinite Noise Multiplier\n");
|
||||
}
|
||||
}
|
||||
for (curdev = devlist; curdev != NULL; i++) {
|
||||
printf("Device: %d, ", i);
|
||||
rc = ftdi_usb_get_strings(ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128);
|
||||
if (rc < 0) {
|
||||
if (!isSuperUser()) {
|
||||
fprintf(stderr, "Can't find Infinite Noise Multiplier. Try running as super user?\n");
|
||||
}
|
||||
fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", rc, ftdi_get_error_string(ftdic));
|
||||
return false;
|
||||
}
|
||||
printf("Manufacturer: %s, Description: %s, Serial: %s\n", manufacturer, description, serial);
|
||||
curdev = curdev->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Initialize the Infinite Noise Multiplier USB interface.
|
||||
static bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) {
|
||||
ftdi_init(ftdic);
|
||||
struct ftdi_device_list *devlist;
|
||||
|
||||
// search devices
|
||||
int rc = 0;
|
||||
if ((rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID)) < 0) {
|
||||
*message = "Can't find Infinite Noise Multiplier\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// only one found, or no serial given
|
||||
if (rc >= 0) {
|
||||
if (serial == NULL) {
|
||||
// more than one found AND no serial given
|
||||
if (rc >= 2) {
|
||||
fprintf(stderr,"Multiple Infnoise TRNGs found and serial not specified, using the first one!\n");
|
||||
}
|
||||
if (ftdi_usb_open(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID) < 0) {
|
||||
if(!isSuperUser()) {
|
||||
*message = "Can't open Infinite Noise Multiplier. Try running as super user?\n";
|
||||
} else {
|
||||
*message = "Can't open Infinite Noise Multiplier\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// serial specified
|
||||
rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial);
|
||||
if (rc < 0) {
|
||||
if(!isSuperUser()) {
|
||||
*message = "Can't find Infinite Noise Multiplier. Try running as super user?\n";
|
||||
} else {
|
||||
*message = "Can't find Infinite Noise Multiplier with given serial\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set high baud rate
|
||||
rc = ftdi_set_baudrate(ftdic, 30000);
|
||||
if(rc == -1) {
|
||||
*message = "Invalid baud rate\n";
|
||||
return false;
|
||||
} else if(rc == -2) {
|
||||
*message = "Setting baud rate failed\n";
|
||||
return false;
|
||||
} else if(rc == -3) {
|
||||
*message = "Infinite Noise Multiplier unavailable\n";
|
||||
return false;
|
||||
}
|
||||
rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB);
|
||||
if(rc == -1) {
|
||||
*message = "Can't enable bit-bang mode\n";
|
||||
return false;
|
||||
} else if(rc == -2) {
|
||||
*message = "Infinite Noise Multiplier unavailable\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Just test to see that we can write and read.
|
||||
uint8_t buf[64u] = {0u,};
|
||||
if(ftdi_write_data(ftdic, buf, 64) != 64) {
|
||||
*message = "USB write failed\n";
|
||||
return false;
|
||||
}
|
||||
if(ftdi_read_data(ftdic, buf, 64) != 64) {
|
||||
*message = "USB read failed\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void initOpts(struct opt_struct *opts) {
|
||||
opts->outputMultiplier = 0u;
|
||||
opts->daemon =
|
||||
opts->debug =
|
||||
opts->devRandom =
|
||||
opts->noOutput =
|
||||
opts->listDevices =
|
||||
opts->raw = false;
|
||||
opts->version = false;
|
||||
opts->help = false;
|
||||
opts->none = false;
|
||||
opts->pidFileName =
|
||||
opts->serial = NULL;
|
||||
}
|
||||
|
||||
// Return the differnece in the times as a double in microseconds.
|
||||
static double diffTime(struct timespec *start, struct timespec *end) {
|
||||
uint32_t seconds = end->tv_sec - start->tv_sec;
|
||||
int32_t nanoseconds = end->tv_nsec - start->tv_nsec;
|
||||
return seconds*1.0e6 + nanoseconds/1000.0;
|
||||
opts->outputMultiplier = 0u;
|
||||
opts->daemon = false;
|
||||
opts->debug = false;
|
||||
opts->devRandom = false;
|
||||
opts->noOutput = false;
|
||||
opts->listDevices = false;
|
||||
opts->raw = false;
|
||||
opts->version = false;
|
||||
opts->help = false;
|
||||
opts->none = false;
|
||||
opts->pidFileName =
|
||||
opts->serial = NULL;
|
||||
}
|
||||
|
||||
// getopt_long(3) options descriptor
|
||||
@@ -390,75 +172,64 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
if (opts.version) {
|
||||
printf("GIT VERSION - %s\n", GIT_VERSION);
|
||||
printf("GIT COMMIT - %s\n", GIT_COMMIT);
|
||||
printf("GIT DATE - %s\n", GIT_DATE);
|
||||
return 0;
|
||||
printf("GIT VERSION - %s\n", GIT_VERSION);
|
||||
printf("GIT COMMIT - %s\n", GIT_COMMIT);
|
||||
printf("GIT DATE - %s\n", GIT_DATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *message = "no data?";
|
||||
bool errorFlag = false;
|
||||
if (opts.listDevices) {
|
||||
listUSBDevices(&ftdic);
|
||||
return 0;
|
||||
if(!listUSBDevices(&ftdic, &message)) {
|
||||
fputs(message, stderr);
|
||||
return 1;
|
||||
}
|
||||
//fputs(message, stdout); // todo: put list of devices to &message and print here, not in libinfnoise
|
||||
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 :-/)
|
||||
#endif
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
int devRandomFD = open("/dev/random", O_WRONLY);
|
||||
if(devRandomFD < 0) {
|
||||
fprintf(stderr, "Unable to open /dev/random\n");
|
||||
exit(1);
|
||||
}
|
||||
close(devRandomFD);
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
message = "dev/random not supported on macOS";
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Optionally run in the background and optionally write a PID-file
|
||||
startDaemon(&opts);
|
||||
|
||||
if(opts.devRandom) {
|
||||
inmWriteEntropyStart(BUFLEN/8u, &opts);
|
||||
}
|
||||
|
||||
if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, &opts)) {
|
||||
fputs("Can't intialize health checker\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
KeccakInitialize();
|
||||
uint8_t keccakState[KeccakPermutationSizeInBytes];
|
||||
KeccakInitializeState(keccakState);
|
||||
|
||||
char *message;
|
||||
if(!initializeUSB(&ftdic, &message, opts.serial)) {
|
||||
// Sometimes have to do it twice - not sure why
|
||||
if(!initializeUSB(&ftdic, &message, opts.serial)) {
|
||||
fputs(message, stderr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Endless loop: set SW1EN and SW2EN alternately
|
||||
uint32_t i;
|
||||
uint8_t outBuf[BUFLEN], inBuf[BUFLEN];
|
||||
for(i = 0u; i < BUFLEN; i++) {
|
||||
// Alternate Ph1 and Ph2
|
||||
outBuf[i] = i & 1? (1 << SWEN2) : (1 << SWEN1);
|
||||
// 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);
|
||||
return 1; // ERROR
|
||||
}
|
||||
|
||||
// endless loop
|
||||
uint64_t totalBytesWritten = 0u;
|
||||
while(true) {
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
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
|
||||
|
||||
if(ftdi_write_data(&ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||
fputs("USB write failed\n", stderr);
|
||||
if (errorFlag) {
|
||||
fprintf(stderr, "Error: %s\n", message);
|
||||
return 1;
|
||||
}
|
||||
if(ftdi_read_data(&ftdic, inBuf, BUFLEN) != BUFLEN) {
|
||||
fputs("USB read failed\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
if(!opts.noOutput && inmHealthCheckOkToUseData() && inmEntropyOnTarget(entropy, BUFLEN)) {
|
||||
uint64_t prevTotalBytesWritten = totalBytesWritten;
|
||||
totalBytesWritten += processBytes(keccakState, bytes, entropy, &opts);
|
||||
if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
|
||||
fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten);
|
||||
}
|
||||
}
|
||||
|
||||
if(opts.debug && (1u << 20u)*(totalBytesWritten/(1u << 20u)) > (1u << 20u)*(prevTotalBytesWritten/(1u << 20u))) {
|
||||
fprintf(stderr, "Output %lu bytes\n", (unsigned long)totalBytesWritten);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1,34 +1,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// Required accuracy of estimated vs measured entropy in health monitor
|
||||
#define INM_ACCURACY 1.03
|
||||
|
||||
// The FT240X has a 512 byte buffer. Must be multiple of 64
|
||||
// We also write this in one go to the Keccak sponge, which is at most 1600 bits
|
||||
#define BUFLEN 512u
|
||||
|
||||
// This is how many previous bits are used to predict the next bit from the INM
|
||||
#define PREDICTION_BITS 14u
|
||||
|
||||
// This is the maximum time we allow to pass to perform the I/O operations, since long
|
||||
// delays can reduce entropy from the INM.
|
||||
#define MAX_MICROSEC_FOR_SAMPLES 5000u
|
||||
|
||||
// This is the gain of each of the two op-amp stages in the INM
|
||||
#define DESIGN_K 1.84
|
||||
|
||||
#define BITMODE_SYNCBB 0x4
|
||||
|
||||
// This defines which pins on the FT240X are used
|
||||
#define COMP1 1u
|
||||
#define COMP2 4u
|
||||
#define SWEN1 2u
|
||||
#define SWEN2 0u
|
||||
|
||||
// All data bus bits of the FT240X are outputs, except COMP1 and COMP2
|
||||
#define MASK (0xffu & ~(1u << COMP1) & ~(1u << COMP2))
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <limits.h>
|
||||
#else
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
#include <ftdi.h>
|
||||
|
||||
// Structure for parsed command line options
|
||||
struct opt_struct {
|
||||
@@ -46,20 +24,4 @@ struct opt_struct {
|
||||
char *serial; // Name of selected device
|
||||
};
|
||||
|
||||
bool inmHealthCheckStart(uint8_t N, double K, struct opt_struct *opts);
|
||||
void inmHealthCheckStop(void);
|
||||
bool inmHealthCheckAddBit(bool evenBit, bool oddBit, bool even);
|
||||
bool inmHealthCheckOkToUseData(void);
|
||||
double inmHealthCheckEstimateK(void);
|
||||
double inmHealthCheckEstimateEntropyPerBit(void);
|
||||
uint32_t inmGetEntropyLevel(void);
|
||||
void inmClearEntropyLevel(void);
|
||||
bool inmEntropyOnTarget(uint32_t entropy, uint32_t bits);
|
||||
void inmWriteEntropyStart(uint32_t bufLen, struct opt_struct *opts);
|
||||
void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy);
|
||||
void inmWaitForPoolToHaveRoom(void);
|
||||
void inmDumpStats(void);
|
||||
void startDaemon(struct opt_struct *opts);
|
||||
bool isSuperUser(void);
|
||||
|
||||
extern double inmK, inmExpectedEntropyPerBit;
|
||||
|
||||
@@ -118,7 +118,7 @@ static void processBytes(uint8_t *keccakState, uint8_t *bytes, uint32_t entropy,
|
||||
return;
|
||||
}
|
||||
// Note that BUFLEN has to be less than 1600 by enough to make the sponge secure,
|
||||
// since outputing all 1600 bits would tell an attacker the Keccak state, allowing
|
||||
// since outputting all 1600 bits would tell an attacker the Keccak state, allowing
|
||||
// him to predict any further output, when outputMultiplier > 1, until the next call
|
||||
// to processBytes. All 512 bits are absorbed before sqeezing data out to insure that
|
||||
// we instantly recover (reseed) from a state compromise, which is when an attacker
|
||||
@@ -245,7 +245,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
*/
|
||||
if(!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) {
|
||||
fputs("Can't intialize health checker\n", stderr);
|
||||
fputs("Can't initialize health checker\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
uint8_t keccakState[KeccakPermutationSizeInBytes];
|
||||
|
||||
457
software/libinfnoise.c
Normal file
457
software/libinfnoise.c
Normal file
@@ -0,0 +1,457 @@
|
||||
/* Library for the Infinite Noise Multiplier USB stick */
|
||||
|
||||
// Required to include clock_gettime
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#define INFNOISE_VENDOR_ID 0x0403
|
||||
#define INFNOISE_PRODUCT_ID 0x6015
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#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__)
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
uint8_t keccakState[KeccakPermutationSizeInBytes];
|
||||
bool initInfnoise(struct ftdi_context *ftdic,char *serial, char **message, bool keccak, bool debug) {
|
||||
prepareOutputBuffer();
|
||||
|
||||
// initialize health check
|
||||
if (!inmHealthCheckStart(PREDICTION_BITS, DESIGN_K, debug)) {
|
||||
*message="Can't initialize health checker";
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize USB
|
||||
if(!initializeUSB(ftdic, message, serial)) {
|
||||
// Sometimes have to do it twice - not sure why
|
||||
if(!initializeUSB(ftdic, message, serial)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize keccak
|
||||
if (keccak) {
|
||||
KeccakInitialize();
|
||||
KeccakInitializeState(keccakState);
|
||||
}
|
||||
|
||||
// let healthcheck collect some data
|
||||
uint32_t maxWarmupRounds = 500;
|
||||
uint32_t warmupRounds = 0;
|
||||
bool errorFlag = false;
|
||||
while(!inmHealthCheckOkToUseData()) {
|
||||
readData_private(ftdic, NULL, message, &errorFlag, false, true, 0, false);
|
||||
warmupRounds++;
|
||||
}
|
||||
if (warmupRounds > maxWarmupRounds) {
|
||||
*message = "Unable to collect enough entropy to initialize health checker.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t outBuf[BUFLEN];
|
||||
void prepareOutputBuffer() {
|
||||
uint32_t i;
|
||||
|
||||
// Endless loop: set SW1EN and SW2EN alternately
|
||||
for(i = 0u; i < BUFLEN; i++) {
|
||||
// Alternate Ph1 and Ph2
|
||||
outBuf[i] = i & 1? (1 << SWEN2) : (1 << SWEN1);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the INM output from the data received. Basically, either COMP1 or COMP2
|
||||
// changes, not both, so alternate reading bits from them. We get 1 INM bit of output
|
||||
// per byte read. Feed bits from the INM to the health checker. Return the expected
|
||||
// bits of entropy.
|
||||
uint32_t extractBytes(uint8_t *bytes, uint8_t *inBuf, char **message, bool *errorFlag) {
|
||||
inmClearEntropyLevel();
|
||||
uint32_t i;
|
||||
for(i = 0u; i < BUFLEN/8u; i++) {
|
||||
uint32_t j;
|
||||
uint8_t byte = 0u;
|
||||
for(j = 0u; j < 8u; j++) {
|
||||
uint8_t val = inBuf[i*8u + j];
|
||||
uint8_t evenBit = (val >> COMP2) & 1u;
|
||||
uint8_t oddBit = (val >> COMP1) & 1u;
|
||||
bool even = j & 1u; // Use the even bit if j is odd
|
||||
uint8_t bit = even? evenBit : oddBit;
|
||||
byte = (byte << 1u) | bit;
|
||||
|
||||
// This is a good place to feed the bit from the INM to the health checker.
|
||||
if(!inmHealthCheckAddBit(evenBit, oddBit, even)) {
|
||||
*message = "Health check of Infinite Noise Multiplier failed!";
|
||||
*errorFlag = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bytes[i] = byte;
|
||||
}
|
||||
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
|
||||
inmWaitForPoolToHaveRoom();
|
||||
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) {
|
||||
//Use the lower of the measured entropy and the provable lower bound on
|
||||
//average entropy.
|
||||
if(entropy > inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY) {
|
||||
entropy = inmExpectedEntropyPerBit*BUFLEN/INM_ACCURACY;
|
||||
}
|
||||
if(raw) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Note that BUFLEN has to be less than 1600 by enough to make the sponge secure,
|
||||
// since outputting all 1600 bits would tell an attacker the Keccak state, allowing
|
||||
// him to predict any further output, when outputMultiplier > 1, until the next call
|
||||
// to processBytes. All 512 bits are absorbed before squeezing data out to ensure that
|
||||
// we instantly recover (reseed) from a state compromise, which is when an attacker
|
||||
// gets a snapshot of the keccak state. BUFLEN must be a multiple of 64, since
|
||||
// Keccak-1600 uses 64-bit "lanes".
|
||||
KeccakAbsorb(keccakState, bytes, BUFLEN/64u);
|
||||
uint8_t dataOut[16u*8u];
|
||||
if(outputMultiplier == 0u) {
|
||||
// Output all the bytes of entropy we have
|
||||
KeccakExtract(keccakState, dataOut, (entropy + 63u)/64u);
|
||||
if (!noOutput) {
|
||||
if (!outputBytes(dataOut, entropy/8u, entropy & 0x7u, writeDevRandom, message)) {
|
||||
*errorFlag = true;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (result != NULL) {
|
||||
memcpy(result, dataOut, entropy/8u * sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
return entropy/8u;
|
||||
}
|
||||
|
||||
// Output 256*outputMultipler bits.
|
||||
uint32_t numBits = outputMultiplier*256u;
|
||||
uint32_t bytesWritten = 0u;
|
||||
|
||||
while(numBits > 0u) {
|
||||
// Write up to 1024 bits at a time.
|
||||
uint32_t bytesToWrite = 1024u/8u;
|
||||
if(bytesToWrite > numBits/8u) {
|
||||
bytesToWrite = numBits/8u;
|
||||
}
|
||||
KeccakExtract(keccakState, dataOut, bytesToWrite/8u);
|
||||
uint32_t entropyThisTime = entropy;
|
||||
if(entropyThisTime > 8u*bytesToWrite) {
|
||||
entropyThisTime = 8u*bytesToWrite;
|
||||
}
|
||||
if (!noOutput) {
|
||||
if (!outputBytes(dataOut, bytesToWrite, entropyThisTime, writeDevRandom, message)) {
|
||||
*errorFlag = true;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
//memcpy(result + bytesWritten, dataOut, bytesToWrite * sizeof(uint8_t)); //doesn't work?
|
||||
// alternative: loop through dataOut and append array elements to result..
|
||||
if (result != NULL) {
|
||||
for (uint32_t i =0; i < bytesToWrite; i++ ) {
|
||||
result[bytesWritten + i] = dataOut[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
bytesWritten += bytesToWrite;
|
||||
numBits -= bytesToWrite*8u;
|
||||
entropy -= entropyThisTime;
|
||||
if(numBits > 0u) {
|
||||
KeccakPermutation(keccakState);
|
||||
}
|
||||
}
|
||||
if(bytesWritten != outputMultiplier*(256u/8u)) {
|
||||
*message = "Internal error outputing bytes";
|
||||
*errorFlag = true;
|
||||
return 0;
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
// Return a list of all infinite noise multipliers found.
|
||||
bool listUSBDevices(struct ftdi_context *ftdic, char** message) {
|
||||
ftdi_init(ftdic);
|
||||
|
||||
struct ftdi_device_list *devlist;
|
||||
struct ftdi_device_list *curdev;
|
||||
char manufacturer[128], description[128], serial[128];
|
||||
int i=0;
|
||||
|
||||
// search devices
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
for (curdev = devlist; curdev != NULL; i++) {
|
||||
//printf("Device: %d, ", i);
|
||||
rc = ftdi_usb_get_strings(ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128);
|
||||
if (rc < 0) {
|
||||
if (!isSuperUser()) {
|
||||
*message = "Can't find Infinite Noise Multiplier. Try running as super user?";
|
||||
return false;
|
||||
}
|
||||
//*message = "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);
|
||||
curdev = curdev->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize the Infinite Noise Multiplier USB interface.
|
||||
bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial) {
|
||||
ftdi_init(ftdic);
|
||||
struct ftdi_device_list *devlist;
|
||||
|
||||
// search devices
|
||||
int rc = 0;
|
||||
if ((rc = ftdi_usb_find_all(ftdic, &devlist, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID)) < 0) {
|
||||
*message = "Can't find Infinite Noise Multiplier";
|
||||
return false;
|
||||
}
|
||||
|
||||
// only one found, or no serial given
|
||||
if (rc >= 0) {
|
||||
if (serial == NULL) {
|
||||
// more than one found AND no serial given
|
||||
if (rc >= 2) {
|
||||
*message = "Multiple Infnoise TRNGs found and serial not specified, using the first one!";
|
||||
}
|
||||
if (ftdi_usb_open(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID) < 0) {
|
||||
if(!isSuperUser()) {
|
||||
*message = "Can't open Infinite Noise Multiplier. Try running as super user?";
|
||||
} else {
|
||||
#ifdef LINUX
|
||||
*message = "Can't open Infinite Noise Multiplier.";
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
|
||||
*message = "Can't open Infinite Noise Multiplier. sudo kextunload -b com.FTDI.driver.FTDIUSBSerialDriver ? sudo kextunload -b com.apple.driver.AppleUSBFTDI ?";
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// serial specified
|
||||
rc = ftdi_usb_open_desc(ftdic, INFNOISE_VENDOR_ID, INFNOISE_PRODUCT_ID, NULL, serial);
|
||||
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 with given serial";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set high baud rate
|
||||
rc = ftdi_set_baudrate(ftdic, 30000);
|
||||
if(rc == -1) {
|
||||
*message = "Invalid baud rate";
|
||||
return false;
|
||||
} else if(rc == -2) {
|
||||
*message = "Setting baud rate failed";
|
||||
return false;
|
||||
} else if(rc == -3) {
|
||||
*message = "Infinite Noise Multiplier unavailable";
|
||||
return false;
|
||||
}
|
||||
rc = ftdi_set_bitmode(ftdic, MASK, BITMODE_SYNCBB);
|
||||
if(rc == -1) {
|
||||
*message = "Can't enable bit-bang mode";
|
||||
return false;
|
||||
} else if(rc == -2) {
|
||||
*message = "Infinite Noise Multiplier unavailable\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Just test to see that we can write and read.
|
||||
uint8_t buf[64u] = {0u,};
|
||||
if(ftdi_write_data(ftdic, buf, 64) != 64) {
|
||||
*message = "USB write failed";
|
||||
return false;
|
||||
}
|
||||
if(ftdi_read_data(ftdic, buf, 64) != 64) {
|
||||
*message = "USB read failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag) {
|
||||
return readData_private(ftdic, result, message, errorFlag, false, true, 0, false);
|
||||
}
|
||||
|
||||
uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier) {
|
||||
return readData_private(ftdic, result, message, errorFlag, false, false, outputMultiplier, false);
|
||||
}
|
||||
|
||||
uint32_t readData_private(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag,
|
||||
bool noOutput, bool raw, uint32_t outputMultiplier, bool devRandom) {
|
||||
uint8_t inBuf[BUFLEN];
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
|
||||
// write clock signal
|
||||
if(ftdi_write_data(ftdic, outBuf, BUFLEN) != BUFLEN) {
|
||||
*message = "USB write failed";
|
||||
*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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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
|
||||
22
software/libinfnoise.h
Normal file
22
software/libinfnoise.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#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>
|
||||
|
||||
// The FT240X has a 512 byte buffer. Must be multiple of 64
|
||||
// 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);
|
||||
|
||||
bool initInfnoise(struct ftdi_context *ftdic, char *serial, char **message, bool keccak, bool debug);
|
||||
|
||||
uint32_t readRawData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag);
|
||||
|
||||
uint32_t readData(struct ftdi_context *ftdic, uint8_t *result, char **message, bool *errorFlag, uint32_t outputMultiplier);
|
||||
5
software/libinfnoise.version
Normal file
5
software/libinfnoise.version
Normal file
@@ -0,0 +1,5 @@
|
||||
libinfnoise {
|
||||
global: listUSBDevices; initInfnoise; readRawData; readData; # explicitly list symbols to be exported
|
||||
local: *; # hide everything else
|
||||
};
|
||||
|
||||
69
software/libinfnoise_private.h
Normal file
69
software/libinfnoise_private.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#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>
|
||||
|
||||
|
||||
#define INFNOISE_VENDOR_ID 0x0403
|
||||
#define INFNOISE_PRODUCT_ID 0x6015
|
||||
|
||||
// Required accuracy of estimated vs measured entropy in health monitor
|
||||
#define INM_ACCURACY 1.03
|
||||
|
||||
// This is how many previous bits are used to predict the next bit from the INM
|
||||
#define PREDICTION_BITS 14u
|
||||
|
||||
// This is the maximum time we allow to pass to perform the I/O operations, since long
|
||||
// delays can reduce entropy from the INM.
|
||||
#define MAX_MICROSEC_FOR_SAMPLES 5000u
|
||||
|
||||
// This is the gain of each of the two op-amp stages in the INM
|
||||
#define DESIGN_K 1.84
|
||||
|
||||
#define BITMODE_SYNCBB 0x4
|
||||
|
||||
// This defines which pins on the FT240X are used
|
||||
#define COMP1 1u
|
||||
#define COMP2 4u
|
||||
#define SWEN1 2u
|
||||
#define SWEN2 0u
|
||||
|
||||
// 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);
|
||||
bool inmHealthCheckOkToUseData(void);
|
||||
double inmHealthCheckEstimateK(void);
|
||||
double inmHealthCheckEstimateEntropyPerBit(void);
|
||||
uint32_t inmGetEntropyLevel(void);
|
||||
void inmClearEntropyLevel(void);
|
||||
bool inmEntropyOnTarget(uint32_t entropy, uint32_t bits);
|
||||
void inmWriteEntropyStart(uint32_t bufLen, bool debug);
|
||||
void inmWriteEntropyToPool(uint8_t *bytes, uint32_t length, uint32_t entropy);
|
||||
void inmWaitForPoolToHaveRoom(void);
|
||||
void inmDumpStats(void);
|
||||
|
||||
extern double inmK, inmExpectedEntropyPerBit;
|
||||
|
||||
bool initializeUSB(struct ftdi_context *ftdic, char **message, char *serial);
|
||||
void prepareOutputBuffer();
|
||||
|
||||
struct timespec;
|
||||
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);
|
||||
1
software/tests/README
Normal file
1
software/tests/README
Normal file
@@ -0,0 +1 @@
|
||||
bats tests for the binary driver.
|
||||
87
software/tests/infnoise.bats
Normal file
87
software/tests/infnoise.bats
Normal file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper/bats-support/load'
|
||||
load 'test_helper/bats-assert/load'
|
||||
|
||||
# Tests for the infnoise binary
|
||||
|
||||
@test "test --raw output for expected entropy" {
|
||||
# capture some data
|
||||
TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX`
|
||||
timeout 5s ./infnoise --raw > $TMP_FILE || true
|
||||
|
||||
# run ent
|
||||
run ent $TMP_FILE
|
||||
|
||||
assert_line --index 0 --regexp '^Entropy = 7.2[5-9][0-9]+ bits per byte.$'
|
||||
|
||||
# cleanup
|
||||
rm $TMP_FILE
|
||||
}
|
||||
|
||||
@test "test whitened output for expected entropy" {
|
||||
# capture some data
|
||||
TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX`
|
||||
timeout 5s ./infnoise > $TMP_FILE || true
|
||||
|
||||
# run ent
|
||||
run ent $TMP_FILE
|
||||
|
||||
# check ent's result
|
||||
assert_line --index 0 --regexp '^Entropy = 7.99[0-9]+ bits per byte.$'
|
||||
|
||||
# cleanup
|
||||
rm $TMP_FILE
|
||||
}
|
||||
|
||||
@test "test whitened output (multiplier=10) for expected entropy" {
|
||||
# capture some data
|
||||
TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX`
|
||||
timeout 5s ./infnoise --multiplier 10 > $TMP_FILE || true
|
||||
|
||||
# run ent
|
||||
run ent $TMP_FILE
|
||||
|
||||
assert_line --index 0 --regexp '^Entropy = 7.99[0-9]+ bits per byte.$'
|
||||
|
||||
# cleanup
|
||||
rm $TMP_FILE
|
||||
}
|
||||
|
||||
@test "test --no-output --debug" {
|
||||
# capture some data
|
||||
TMP_FILE=`mktemp -u $BATS_TMPDIR/infnoise-test-XXXXXXX`
|
||||
run timeout 5s ./infnoise --no-output --debug
|
||||
|
||||
echo $output
|
||||
[ "$status" -eq 124 ]
|
||||
|
||||
assert_line --index 0 --regexp '^Generated 1048576 bits. OK to use data. Estimated entropy per bit: 0\.[0-8][6-8][0-9]+, estimated K: 1\.8[1-5][0-9]+$'
|
||||
assert_line --index 1 --regexp '^num1s:50.[0-9]+%, even misfires:0.[0-1][0-9]+%, odd misfires:0.[0-1][0-9]+%$'
|
||||
}
|
||||
|
||||
@test "test --list-devices" {
|
||||
run ./infnoise --list-devices
|
||||
echo $output
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# FTDI serial:
|
||||
assert_line --index 1 --regexp '^Manufacturer: FTDI, Description: FT240X USB FIFO, Serial: [0-9A-Z]+$'
|
||||
|
||||
# 13-37.org serial:
|
||||
assert_line --index 0 --regexp '^Manufacturer: 13-37.org, Description: Infinite Noise TRNG, Serial: [0-9A-F]+$'
|
||||
}
|
||||
|
||||
@test "test --serial with not connected serial (results in error)" {
|
||||
run ./infnoise --serial 4711
|
||||
echo $output
|
||||
[ "$status" -eq 1 ]
|
||||
[ "${lines[0]}" = "Can't find Infinite Noise Multiplier. Try running as super user?" ]
|
||||
}
|
||||
|
||||
@test "test --help" {
|
||||
run ./infnoise --help
|
||||
echo $output
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${lines[0]}" = "Usage: infnoise [options]" ]
|
||||
}
|
||||
1
software/tests/test_helper/bats-assert
Submodule
1
software/tests/test_helper/bats-assert
Submodule
Submodule software/tests/test_helper/bats-assert added at 9f88b4207d
1
software/tests/test_helper/bats-support
Submodule
1
software/tests/test_helper/bats-support
Submodule
Submodule software/tests/test_helper/bats-support added at 004e707638
@@ -35,10 +35,10 @@ int main(int argc, char **argv) {
|
||||
uint32_t i;
|
||||
printf("password:");
|
||||
for (i = 0u; i < keys; i++) {
|
||||
uint32_t randVal = rollDie(26u, file);
|
||||
uint32_t randVal = rollDie(32u, file);
|
||||
putchar('a' + randVal);
|
||||
}
|
||||
printf("\nThis password has %.2f bits of entropy\n", log(pow(26.0, keys))/log(2));
|
||||
printf("\nThis password has %.2f bits of entropy\n", log(pow(32.0, keys))/log(2));
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/random.h>
|
||||
#include "infnoise.h"
|
||||
#include "libinfnoise.h"
|
||||
|
||||
#define SIZE_PROC_FILENAME "/proc/sys/kernel/random/poolsize"
|
||||
#define FILL_PROC_FILENAME "/proc/sys/kernel/random/write_wakeup_threshold"
|
||||
@@ -40,9 +40,10 @@ static uint32_t readNumberFromFile(char *fileName) {
|
||||
}
|
||||
|
||||
// Open /dev/random
|
||||
void inmWriteEntropyStart(uint32_t bufLen, struct opt_struct* opts) {
|
||||
void inmWriteEntropyStart(uint32_t bufLen, bool debug) {
|
||||
inmBufLen = bufLen;
|
||||
inmDebug = opts->debug;
|
||||
inmDebug = debug;
|
||||
|
||||
//inmDevRandomFD = open("/dev/random", O_WRONLY);
|
||||
inmDevRandomFD = open("/dev/random", O_RDWR);
|
||||
if(inmDevRandomFD < 0) {
|
||||
|
||||
Reference in New Issue
Block a user