FN-DSA is a new upcoming post-quantum signature scheme, currently being defined by NIST as part of their Post-Quantum Cryptography Standardization project. FN-DSA is based on the Falcon scheme.
WARNING: As this file is being written, no FN-DSA draft has been published yet, and therefore what is implemented here is not the "real" FN-DSA; such a thing does not exist yet. When FN-DSA gets published (presumably as a draft first, but ultimately as a "final" standard), this implementation will be adjusted accordingly. Correspondingly, it is expected that backward compatiblity will NOT be maintained, i.e. that keys and signatures obtained with this code may cease to be accepted by ulterior versions. Only version 1.0 will provide such stability, and it will be published only after publication of the final FN-DSA standard.
This implementation is the C variant of the Rust implementation. It is interoperable (indeed, it reproduces the same test vectors) and mostly has feature parity and similar performance, with the following notes:
-
The C code's external API is in fndsa.h. This is the only file that application code needs to include.
-
The files
codec.c
,mq.c
,sha3.c
,sysrng.c
andutil.c
are used for all operations. The fileskgen*.c
are used only for key pair generation. They can be omitted if not generating key pairs. Similary, thesign*.c
files are only for signature generation, andvrfy.c
is used only for signature verification. Typically, an application that only needs to verify signatures can avoid the code footprint cost of including the "kgen" and "sign" files. -
The
speed_fndsa.c
andtest*.c
files are only for benchmarks and tests. -
The API works only with keys in their encoded formats. Contrary to the Rust code, there is no "state" object that can be built and store reusable values across subsequent operations. Temporary buffers are normally allocated from the stack, but they can also be provided externally for builds targeting small embedded systems with shallow stacks.
-
When random bytes are needed, the operating system's RNG is invoked. This supports Windows and Unix-like systems (including Linux and macOS). For unsupported systems (including bare metal OS-less systems), the API has the option for the caller to provide a seed on which to work. It is then up to the caller to provide an adequately-sized seed with enough entropy (in general, aim for at least 256 bits of entropy).
For build options, see the Makefile. In general, the code should work fine without needing much fiddling.
The implementation includes some assembly routines (some inline, and some in separate assembly source files) which offer substantial speed-ups, especially for signature generation, when running the code on an ARM Cortex-M4F CPU. See Makefile.cm4 for compiling that code with a cross-compiling system toolchain. Alternatively, see the bench_cm4/ subdirectory for a benchmarking application that can run on an STM32F407G-DISC1 board (using an STM32F4 microcontroller).