
Photo: leetronics.de
OpenSSL 3.x provider for the Infinite Noise TRNG USB hardware random number generator.
This provider registers an OSSL_OP_RAND seed source backed by the Infinite Noise TRNG, a USB true random number generator based on modular entropy multiplication. When configured as the DRBG seed source, all OpenSSL cryptographic operations (key generation, signatures, TLS handshakes) are seeded with hardware entropy.
Written from scratch for the OpenSSL 3.x Provider API. A legacy ENGINE implementation by Tim Skipper exists at tinskip/infnoise-openssl (dormant since 2020); this provider shares no code with it.
Independent implementation. This project is not affiliated with or endorsed by the upstream Infinite Noise TRNG project (waywardgeek/infnoise) or the vendor I bought it from (https://leetronics.de/en/shop/infinite-noise-trng/).
Alpha software (current tag:
v0.0.2-alpha). Passes a 29-test integration harness, four libFuzzer harnesses at 96.1% line coverage, a 24-hour endurance run, and the ASan / UBSan / TSan / allocator-failure sanitiser matrix — but has not been independently audited. Do not use this to seed production key material without your own review. See SECURITY.md for the disclosure policy, docs/Security_Review.txt for the brief prepared for an external reviewer, and docs/TODO.txt for the path to beta.
- OpenSSL 3.x (tested with 3.4+)
- libinfnoise and its dependency libftdi1. The provider requires a libinfnoise build whose header defines
INFNOISE_KECCAK_STATE_SIZE— per-context Keccak/health state and signed-int32_treadData()return. Both patches merged into waywardgeek/infnoise master on 2026-05-15 (#121, #122); any libinfnoise built from upstream master onwards works. The build will fail with a clear#errorif linked against an older libinfnoise. - Infinite Noise TRNG USB device connected
- GCC with C11 support
- pkg-config (used by the Makefile to locate libcrypto and libftdi1)
- Linux (tested on Arch Linux; should work on any distro with the above)
# libftdi1 is in the official repos
pacman -S libftdi openssl pkgconf
# libinfnoise from upstream master (carries the required patches as of
# waywardgeek/infnoise#121 and #122). Distro packages may lag until
# they pick up a release tag containing those commits.
git clone https://github.com/waywardgeek/infnoise /tmp/infnoise
make -C /tmp/infnoise/software -f Makefile.linux libinfnoise.so
sudo make -C /tmp/infnoise/software -f Makefile.linux PREFIX=/usr install-lib
sudo ldconfigapt install libftdi1-dev libssl-dev pkg-config build-essential
# libinfnoise from upstream master, same reason as above.
git clone https://github.com/waywardgeek/infnoise /tmp/infnoise
make -C /tmp/infnoise/software -f Makefile.linux libinfnoise.so
sudo make -C /tmp/infnoise/software -f Makefile.linux PREFIX=/usr install-lib
sudo ldconfigmakeThis produces infnoise.so — a hardened shared library (Full RELRO, stack canary, CET/IBT, NX, PIE, stripped).
To install into the OpenSSL modules directory (typically /usr/lib/ossl-modules/):
sudo make installOptional — build and install the manpage (requires pandoc):
make man
sudo make install-man # → /usr/share/man/man7/OSSL_PROVIDER-infnoise.7
man OSSL_PROVIDER-infnoiseCopy or symlink conf/infnoise-provider.cnf and point OpenSSL at it:
export OPENSSL_CONF=conf/infnoise-provider.cnfOr append the relevant sections to your system /etc/ssl/openssl.cnf:
[provider_sect]
default = default_sect
infnoise = infnoise_sect
[default_sect]
activate = 1
[infnoise_sect]
module = /usr/lib/ossl-modules/infnoise.so
activate = 1
[random_sect]
seed = infnoiseConfirm the TRNG is detected:
# List USB devices — should show "13-37.org / Infinite Noise TRNG"
lsusb | grep 0403:6015
# Quick test with the infnoise CLI (from upstream package)
infnoise --list-devicesVerify the provider loads and generates entropy:
# Check provider is recognized
openssl list -providers -provider-path /usr/lib/ossl-modules -provider infnoise
# Generate random bytes through the provider
OPENSSL_CONF=conf/infnoise-provider.cnf openssl rand -hex 64
# Statistical quality check (requires ent)
OPENSSL_CONF=conf/infnoise-provider.cnf openssl rand 1000000 | entGenerate keys using hardware entropy:
OPENSSL_CONF=conf/infnoise-provider.cnf openssl genrsa 4096
OPENSSL_CONF=conf/infnoise-provider.cnf openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256The test arsenal:
make test— 29-test integration harness across 5 layers (hardware, provider API, integration, statistical, memory safety).make test-asan/test-ubsan/test-valgrind— sanitiser builds against the integration harness.make test-tsan— ThreadSanitizer concurrency stress, 4 threads × 20 000 iterations × 2 scenarios. No hardware needed.make test-alloc—CRYPTO_set_mem_functionsfailure injection at four alloc sites. No hardware needed.make fuzz FUZZ_CC=clang— four libFuzzer harnesses (dispatch / ossl_params / spill_oracle / provider_init) undertests/fuzz/. Coverage 294 of 306 lines (96.1%); 23 of 23 functions executed. See docs/Fuzz_Coverage.txt.make test-soak/test-soak-short— 24-hour / 1-hour endurance run through the provider; details below.make lint— cppcheck +gcc -fanalyzerstatic analysis.make sbom— SPDX-2.3 software bill of materials atsbom.spdx.txt.
See docs/Testing.txt for invocations and the per-layer breakdown.
make test-soak drove EVP_RAND continuously for 24 hours: 14 698 generate calls, 4.21 GiB produced (49.9 KiB/s sustained), 0 errors, 95 instantiate / uninstantiate cycles. RSS peaked at +1.2 MiB and ended 1.0 MiB below start — bounded growth, no leaks.
The two plots below visualise the same entropy stream from two angles. The pair-wise scatter is the most striking: raw TRNG output exposes the Modular Entropy Multiplier's preferred bit states as a regular grid; after Keccak whitening the structure is gone and the byte plane fills uniformly.
The byte-value heatmap shows each byte as a coloured pixel (0 black → 255 white). Raw output has warmer clumps where the multiplier favours mid-range values; whitening flattens the texture into uniform fine-grain noise.
These plots show that whitening removes visible structure — statistical uniformity, not min-entropy. A uniform-looking byte plane is necessary but not sufficient for unpredictability; a hash of a counter would look identical. DRBG strength is governed by the seed's measured min-entropy, which is why
get_seedsizes seeds by min-entropy (~3 bits per output byte) rather than by how random the output looks. See docs/ARCHITECTURE.txt ("Seed entropy accounting").
By default, the FTDI device requires root access. To use without root, create a udev rule:
# /etc/udev/rules.d/75-infnoise.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", \
GROUP="plugdev", MODE="0664", TAG+="uaccess"Then reload udev and add your user to the group:
sudo udevadm control --reload-rules
sudo usermod -aG plugdev $USER
# Log out and back in for group change to take effect| Path | Description |
|---|---|
src/infnoise_prov.c |
Provider implementation |
tests/test_infnoise_prov.c |
Integration test harness (29 tests) |
tests/test_infnoise_tsan.c |
ThreadSanitizer concurrency stress (make test-tsan) |
tests/test_infnoise_alloc.c |
Allocator-failure injection (make test-alloc) |
tests/test_infnoise_soak.c |
24-hour soak: drives EVP_RAND through every spill-buffer phase, cycles instantiate/uninstantiate, tracks RSS for leaks, dumps rolling samples for ent/rngtest/dieharder |
tests/fuzz/ |
4 libFuzzer harnesses (see docs/Fuzz_Coverage.txt) plus the mock libinfnoise stub for fuzz and test builds |
tests/fuzz/corpus/ |
Persistent fuzz corpus per harness, committed for replay |
tests/fuzz/regressions/ |
Inputs that triggered fixed bugs, replayed first by CIFuzz |
tests/mutation/ + mull.yml |
Mull mutation-testing harness (release-prep, make mutation) |
examples/ |
Drop-in usage examples (Python keygen, systemd scoping) |
conf/infnoise-provider.cnf |
OpenSSL configuration |
conf/openssl.supp |
Valgrind suppressions |
docs/ARCHITECTURE.txt |
Design decisions and security analysis |
docs/Build_Security.txt |
Binary hardening + runtime security properties |
docs/CONTRIBUTING.txt |
Contribution guidelines |
docs/FAQ.txt |
Common questions |
docs/Fuzz_Coverage.txt |
Per-function fuzz coverage report |
docs/Governance.txt |
Maintainer model, authentication, signing-key plan |
docs/OSSL_PROVIDER-infnoise.7.md |
Pandoc source for the section-7 manpage |
docs/Security_Review.txt |
Brief for an external cryptographic reviewer |
docs/Testing.txt |
Test harness layers and invocations |
docs/TODO.txt |
Deferred work toward beta |
.github/ |
Issue and pull-request templates, CI workflows |
.editorconfig |
Editor style rules |
SECURITY.md |
Vulnerability disclosure policy |
CHANGELOG.md |
Keep-a-Changelog 1.1.0 |
CODE_OF_CONDUCT.md |
Contributor Covenant 2.1 |
CONTRIBUTING.md |
Shim pointing at docs/CONTRIBUTING.txt |
Makefile |
Build system |
LICENSE |
GPL-2.0-or-later |
Full binary hardening (RELRO, stack canary, CET/IBT, NX, PIE, FORTIFY_SOURCE=3, stripped), entropy-buffer cleansing on all paths, secure-heap seed allocation (OPENSSL_secure_malloc — mlock'd when the application initialises OpenSSL's secure heap before the first call; see docs/ARCHITECTURE.txt §5), bounded request sizes, and thread-safe dispatch. See docs/Build_Security.txt for the full list and docs/ARCHITECTURE.txt for the design rationale. Vulnerability disclosure: SECURITY.md. Maintainer / signing model: docs/Governance.txt.
- One open handle per physical device. FTDI USB exclusion applies regardless of provider configuration; multiple
EVP_RAND_CTXinstances against the same TRNG would race for the device. The provider serialises a single shared context viaCRYPTO_RWLOCK. - Throughput ~50 KB/s (USB bulk transfer speed bound). Suitable for seeding DRBGs and key generation; not suitable for bulk random data production.
Patches, bug reports, and feature proposals are welcome. See docs/CONTRIBUTING.txt for style, build / test expectations, and the security invariants that any change must preserve. All participation is governed by the Code of Conduct.
For suspected vulnerabilities, please follow SECURITY.md rather than opening a public issue.
GPL-2.0-or-later. See LICENSE for details.
This provider links OpenSSL (Apache 2.0). Pure GPL-2.0 is incompatible with Apache 2.0; the "or later" clause elevates the effective license to GPL-3.0 at distribution time, which is explicitly Apache-2.0-compatible.
Copyright (C) 2025-2026 Avinash H. Duduskar.

