lean cryptography in every aspect

leancrypto Cryptographic Library

leancrypto offers a lean and versatile cryptographic library building on Post Quantum Cryptography.

Study and Analysis of Cryptography

Papers study and analyze various aspects of cryptographic algorithms and use cases.

XDRBG Specification and Reference Implementation

XDRBG provides the documentation of the XDRBG random number generator algorithm along with a reference implementation.

Subsections of lean cryptography in every aspect

Leancrypto

Properties of leancrypto

The leancrypto library is a cryptographic library that exclusively contains only PQC-resistant cryptographic algorithms. The algorithm implementations have the following properties:

  • minimal dependencies: only minimal POSIX environment needed - function calls are abstracted into helper code that may need to be replaced for other environments:

  • extractable: the algorithms can be extracted and compiled as part of a separate project,

  • flexible: you can disable algorithms on an as-needed basis using meson configure,

  • fully thread-safe when using different cipher contexts for an invocation: there is no global state maintained for the algorithms,

  • stack-only support: all algorithms can be allocated on stack if needed. In addition, allocation functions for a usage on heap is also supported,

  • size: minimizing footprint when statically linking by supporting dead-code stripping,

  • performance: provide optimized code invoked with minimal overhead, thus significantly faster compared to other libraries like OpenSSL,

  • testable: all algorithm implementations are directly accessible via their data structures at runtime - regularly executed tests:

    • All algorithms testable with NIST’s ACVP are tested and official CAVP certificates are received

    • Automated test system using the meson build system covering all algorithms

    • Automated testing of various scenarios using Github Testing

    • Automated testing of various CPU architectures using OpenSUSE Build Service

    • Continuous testing for Memory Leaks

    • Continuous Security Scans

  • versatile: The following execution environments are supported with all accelerated implementations:

    • Linux user space

    • Linux kernel space

    • BSD user space

    • Apple OSes user space

    • Windows user space

  • accelerated: Accelerated implementations are provided for the following algorithms which also benefit aggregated algorithms building on those primitives:

    • Ascon permutation: x86_64

    • SHA-3 and derivatives: x86_64, ARMv8, ARMv7

    • Curve 25519: x86_64

    • ML-DSA / Dilithium: x86_64, ARMv8, ARMv7

    • ML-KEM / Kyber: x86_64, ARMv8, ARMv8

    • SLH-DSA / Sphincs+: x86_64, ARMv8

    • AES: x86_64 AES-NI, ARMv8 CE and assembler, ARMv7

  • side-channel-resistant: A valgrind-based dynamic side channel analysis is applied to find time-variant code paths based on secret data.

Subsections of Leancrypto

Subsections of Releases

Leancrypto Version 1.1.0

Code

Changes 1.1.0

  • ML-KEM remove modulus check of decapsulation key (not required by FIPS 203)

  • ML-KEM: add key pair PCT API - leancrypto cannot invoke it itself as it does not know when both keys are provided from outside

  • ML-DSA: add consistency with FIPS 204 - the signature changes as the input data handling is added (if you want to apply the old signature, use the new lc_dilithium_[sign|verify]_ctx API with ctx->ml_dsa_internal = 1)

  • ML-DSA: add API to allow caller to provide a user context as allowed by FIPS 204, to invoke ML-DSA.Sign_internal, ML-DSA.Verify_internal and HashML-DSA

  • ML-KEM: rename source code directory to ml-kem

  • ML-DSA: rename source code directory to ml-dsa

  • BIKE: Add NIST round 4 KEM candiate

  • ML-DSA: Add support to retain the expanded key to increase the performance of signature operations by 15 to 20%

  • ML-DSA: add key pair PCT API - leancrypto will not invoke it, but provides it for FIPS 140 support

  • SLH-DSA: Add SLH-DSA-SHAKE-256s, SLH-DSA-SHAKE-256f, SLH-DSA-SHAKE-192s, SLH-DSA-SHAKE-192f, SLH-DSA-SHAKE-128s, SLH-DSA-SHAKE-128f

  • ML-DSA, ML-KEM, SLH-DSA, BIKE, Hash, AEAD, RNG, HMAC, HKDF, symmetric: move API implementation from H to C file - this implies that no RUST wrappers are needed

  • Linux kernel: ML-DSA / SLH-DSA sigver input changed to be compliant to existing kernel structures: req->src SGL contains signature || msg, req->dst SGL is not processed

Leancrypto Version 1.0.1

Code

Changes 1.0.1

  • fix: Kyber keygen - add LC_KYBER_K to initial hash (change is only relevant when storing keys as seed and for interoperability)

  • fix: Dilithium keygen - add dimensions K and L (change is only relevant when storing keys as seed and for interoperability)

  • small performance improvements for hasher apps

Leancrypto Version 1.0.0

Code

Changes 1.0.0

  • enhancement: add Doxygen support - it is automatically compiled if Doxygen is present

  • enhancement: add Dilithium-ED25519 stream mode operation (i.e. init/update/final)

  • due to the Dilithium-ED25519 stream mode support, the Dilithium-ED25519 now used ED25519ph signature algorithm mode

  • Dilithium API change: the stream mode uses struct lc_dilithium_ctx instead of lc_hash_ctx to reflect the newly added Dilithium-ED25519 API - the lc_dilithium_ctx can be allocated on the stack or heap using LC_DILITHIUM_CTX_ON_STACK or lc_dilithium_ctx_alloc

  • enhancement: add Dilithium-ED25519 as Linux kernel akcipher algorithm

  • enhancement: make Kyber-X25519 as Linux kernel kpp algorithm consistent with the standalone Kyber kpp implementation and add a tester

  • seeded_rng: when using the ESDM as entropy source, use DRBG without prediction resistance. When having heavy respawning of applications, using the PR DRBG will strain the entropy source significantly.

  • Dilithium: add edge case tests as referenced by https://github.com/usnistgov/ACVP/pull/1525.patch and https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/G8Zf0hC-uu0/m/Kb3qNJb0AwAJ

Leancrypto Version 0.11.0

Code

Changes 0.11.0

  • security fix: fix possible leak of message in Kyber

  • Kyber: reduce memory footprint, use common lc_memcmp_secure API

  • Ascon-Keccak: include the tag length into the IV and thus implicitly authenticate the tag length (thanks to Markku-Juhani Saarinen to suggest this)

  • Kyber: change standard API such that caller can select Kyber type

  • Dilithium: change standard API such that caller can select Dilithium type

  • security: addition of Timecop and instrumentation of tests to find side-channels

  • enhancement: add Linux kernel crypto API support for Ascon / Ascon-Keccak

  • fix: performance of seeded RNG by setting reseed threshold to 1MB

  • fix: Linux kernel warning on return thunk

  • enhancement: add ASM ARMv7 and ARMv8 implementation for X25519

  • enhancement: add Ascon support for XDRBG

  • enhancement: performance increase for XDRBG256

  • enhancement: add ED25519ph to support Dilithium hybrid init/update/final handling

Leancrypto Version 0.10.1

Code

Changes 0.10.1

  • enhancement: Linux kernel - Kyber: allow parallel compilation of all Kyber types including all optimizations

  • enhancement: Linux kernel - Dilithium: allow parallel compilation of all Dilithium types including all optimizations

  • add additional hardening compiler flags stipulated by openssf.org

Changes 0.10.0

  • enhancement: add Sponge APIs

  • enhancement: add Ascon Keccak 512 and 256

Leancrypto Version 0.10.0

Code

Changes 0.10.0

  • enhancement: add Sponge APIs

  • enhancement: add Ascon Keccak 512 and 256

  • update AEAD: add lc_aead_enc|dec_init and change all AEAD algo’s tag calculation to now perform MAC(AAD || ciphertext) instead of MAC(ciphertext || AAD) - this brings it in line with all AEAD algorithms

  • enhancement: add Ascon AEAD 128 and 128b

  • rename API lc_shake to lc_xof

  • enhancement: add Ascon Hash 128 and 128a

  • enhancement: add Ascon XOF and XOFa

  • enhancement: add Ascon 128/128a hasher apps

  • large data tests can now execute on small systems by using smaller memory sizes

  • remove riscv64 hash assembler directory: it is a duplicate of the riscv32 assembler code

  • Kyber 768: Add AVX2, ARMv8, ARMv7 support

  • Dilithium 65: Add AVX2, ARMv8, ARMv7 support

  • Enable compilation of Kyber 1024, Kyber-768 and Kyber-512 at the same time (APIs starting with lc_kyber_768/lc_kex_768 refer to Kyber-768, APIs starting with lc_kyber_512/lc_kex_512 refer to Kyber-512, all others refer to Kyber-1024)

  • Enable compilation of Dilithium 87, Dilithium-65 and Dilithium-44 at the same time (APIs starting with lc_dilithium_65 refer to Dilithium-768, APIs starting with lc_dilithium_44 refer to Dilithium-44, all others refer to Dilithium-87)

  • enhancement: Windows is now supported as target platform using the MINGW compiler with full acceleration support

  • Dilithium: update SampleInBall implementation following https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/y8ul-ZcVWI4 - implementation is fully checked against NIST ACVP Demo server

Leancrypto Version 0.9.2

Code

Changes 0.9.2

  • fix: update “reduce memory footprint of Keccak state” to handle big-endian systems

  • enhancement: Seed the lc_seeded_rng with (random.c || Jitter RNG)

Leancrypto Version 0.9.1

Code

Changes 0.9.1

  • fix: move XOR-256 memory definitions to lc_memory_support.h as otherwise compilation of external applications and libraries fail due to missing xor256.h

Leancrypto Version 0.9.0

Code

Changes 0.9.0

  • enhancement: X/ED25519: enable 128 bit mode on Intel for both, kernel and user space

  • add Rust binding support

  • enhancement: reduce memory footprint of Keccak state

  • enhancement: add cSHAKE re-init support

  • fix: KMAC-AEAD / cSHAKE-AEAD - ensure proper re-initialization

  • enhancement: add RISC-V 64 bit Keccak - currently disabled due to a bug

  • enhancement: compile Dilithium ARMv8 support in Linux kernel (excluding the SIMD Keccak operation)

  • fix: fix ARM-CE detection logic

  • fix: potential Kyber side channel

  • fix: KMAC min MAC size is 32 bits

  • enhancement: use accelerated XOR for KMAC/cSHAKE AEAD

  • fix: enable poly_compress_avx for Linux kernel compilation when GCC >= 13 is present

  • enhancement: add interface code to register leancrypto with Linux kernel crypto API

Leancrypto Version 0.8.0

Code

Changes 0.8.0

  • enhancement: add applications

  • enhancement: add Dilithium ARMv8 support (including SHAKE 2x ARMv8 support)

  • enhancement: add Dilithium ARMv7 support

  • enhancement: add Kyber ARMv7 support

  • reduce memory footprint of Dilithium and Kyber

  • enhancement: Add Kyber-X25519 KEM, KEX, and IES

  • enhancement: Add Dilithium-ED25519

  • hardening: use -fzero-call-used-regs=used-gpr if available to counter ROP attacks

  • fix: Add fork-detection for seeded_rng

  • update XDRBG256 implementation based on latest draft

Leancrypto Version 0.7.0

Code

Changes 0.7.0

  • enhancement: add XDRBG256 - the SHAKE256-based DRNG discussed for SP800-90A inclusion (almost idential to cSHAKE/KMAC DRNG specified with leancrypto)

  • enhancement: add SymKMAC AEAD algorithm - it uses 100 bytes less context than SymHMAC (it is less than 1024 bytes now), uses accelerated Keccak for KDF and authentication but is otherwise identical to SymHMAC

  • Kyber: switch responder and initiator definitions

  • enhancement: add ESDM seed source to seed lc_seeded_rng

  • editorial: reformat code using clang-format and provided configuration file

  • Dilithium: Update implementation to match FIPS 204 (draft from Aug 24, 2023)

  • Kyber: Update implementation to match FIPS 203 (draft from Aug 24, 2023)

  • enhancement: Dilithium and Kyber security strengths are selectable via Meson options

  • Kyber KEM: Update shared secret KDF (as the KDF is now removed from FIPS 203, it can be adjusted to be more performant and consistent with SP800-108)

  • Kyber KEX: Updated shared secret KDF to use SP800-108 compliant KMAC KDF

  • enhancement: Add input parameter validatino to Kyber as specified in FIPS 203

  • enhancement: consolidate all testing requiring an RNG to use selftest_rng

Leancrypto Version 0.6.0

Code

Changes 0.6.0

  • enhancement: Linux - add memfd_secret(2) support for secure memory allocation

  • fix: documentation of lc_kyber_keypair

  • enhancement: remove the rng_ctx parameter in all Kyber APIs except the key generation - internally lc_seeded_rng is used instead

  • enhancement: use -Wmissing-prototypes and fix reported issues

  • enhancement: provide standalone CBC, CTR, KW implementation

  • enhancement: provide AESNI implementation

  • enhancement: provide AES ARM CE implementation

  • enhancement: provide AES RISC-V 64 assembler implementation

  • enhancement: provide Linux kernel configuration option to enable startup health tests

  • fix: apply fixes such that all self tests and regression tests pass when compiled for Linux kernel

  • fix: properly zeroize memory when using the workspace memory

Leancrypto Version 0.5.3

Code

Changes 0.5.3

  • convert to safe min/max implementations

  • enhancement: allow kernel modules to be compiled directly from installed user space headers

  • enhancement: make ARMv8 code compile on macOS

  • use O3 compiler optimization instead of Os - O3 is significantly faster especially for Kyber C implementation, yet both options work fine

Leancrypto Version 0.5.2

Code

Changes 0.5.2

  • enhancement: add ARMv7 Neon assembler support for Keccak

  • enhancement: add but disable ARMv8 Neon assembler support for Keccak (it is slower than optimized C)

  • enhancement: add sign/update/final Dilithium APIs

  • enhancement: add RISC-V assembler support for Keccak (yet disabled)

  • enhancement: add ARMv8 assembler implementation of Kyber

  • enhancement: add counter KDF RNG interface

  • enhancement: add ARMv8 assembler and ARMv8 CE Keccak support

Leancrypto Version 0.5.1

Code

Changes 0.5.1

  • enhancement: add Linux kernel configuration options

  • enhancement: add lc_rerun_selftests API

  • enhancement: add AVX2 support for memcmp_secure

  • fix: some comments

Leancrypto Version 0.5.0

Code

Changes 0.5.0

  • enhancement: add ability to compile leancrypto for the Linux kernel including all tests

  • enhancement: make leancrypto generic such that it can be used in environments other than user space

  • enhancement: add compile time option small_stack which ensures that leancrypto’s stack usage is always less than 2048 (also verified by the compiler warning if it is bigger)

  • enhancement: Add assembler accelerations for SHA3 (AVX2 and AVX512 are verified with NIST’s ACVP service)

  • bug fix: Fix the SHA-3 C implementation on big-endian system (one byte-swap missing)

  • bug fix: SHAKE128 state had wrong size causing an overflow with the memset_secure in lc_hash_zero

  • fix: remove compile-time warnings on 32 bit systems

  • enhancement: SHAKE AVX2 4x implementation used by Kyber AVX2 implementation

  • enhancement: Kyber AVX2 support

  • enhancement: Dilithium AVX2 support

  • leancrypto tested on macOS with an M2 system

  • bug fix: Dilithium C on Big Endian had implicit type casts leading to endianess issues

  • enhancement: add RPM SPEC file - successful build on OpenSUSE build service on x86_64, i586, aarch64, armv7l, armv6l, ppc64, ppc64le, riscv64

  • rename memset_secure to lc_memset_secure preventing any possible name space clash

  • enhancement: add self tests to all algorithms

  • bug fix: ChaCha20 on BigEndian systems

Leancrypto Version 0.4.0

Code

Changes 0.4.0

  • simplify Kyber code

  • add RNG context to HKDF

  • add RNG context to KMAC

  • add AES 128/192/256, ECB, CBC, CTR, KW

  • add lc_seeded_rng

  • add lc_aead API to provide common interface to AEAD algorithms

  • add KyberIES

  • change API to Kyber KEM: allow caller to specify size of generated key

  • add leancrypto.h for ease of use

  • add SymHMAC AEAD algorithm

  • add cSHAKE 128

  • add KMAC 128

Leancrypto Version 0.3.0

Code

Changes 0.3.0

  • Introduce lc_rng.h as a common interface to the random number generators

  • add KMAC DRNG

  • add cSHAKE DRNG

  • add SHAKE-128

  • add dilithium signature PQC schema - test vectors were generated by leancrypto, but compared with the reference implementation which calculate the same results

  • add kyber KEM PQC schema - test vectors were generated by leancrypto, but compared with the reference implementation which calculate the same results

  • add cSHAKE AEAD cipher

  • KMAC-AEAD cipher: auth key is now set to 256 bits

Build Instructions

Building User Space Library

If you want to build the leancrypto shared library, use the provided Meson build system:

  1. Setup: meson setup build

  2. Compile: meson compile -C build

  3. Test: meson test -C build

  4. Install: meson install -C build

Building Linux Kernel Library

The leancrypto library can also be built as an independent Linux kernel module. This kernel module offers the same APIs and functions as the user space version of the library. This implies that a developer wanting to develop kernel and user space users of cryptographic mechanisms do not need to adjust to a new API.

Note: The user space and kernel space versions of leancrypto are fully independent of each other. Neither requires the presence of the other for full operation.

To build the leancrypto Linux kernel module, use the Makefile in the directory linux_kernel:

  1. cd linux_kernel

  2. make

  3. the leancrypto library is provided with leancrypto.ko

Note, the compiled test kernel modules are only provided for regression testing and are not required for production use. Insert the kernel modules and check dmesg for the results. Unload the kernel modules afterwards.

The API specified by the header files installed as part of the meson install -C build command for the user space library is applicable to the kernel module as well. When compiling kernel code, the flag -DLINUX_KERNEL needs to be set.

Library Build for Windows

The leancrypto library can be built on Windows using MSYS2. Once MSYS2 is installed along with meson and the mingw compiler, the standard compilation procedure outlined above for meson can be used.

The support for full assembler acceleration is enabled.

Building for Other Environments

If you need leancrypto to work in other environments like small embedded systems, you need:

  1. Adjust the build system as needed to compile and link it

  2. Adjust the file ext_headers.h to point to the right header files and locations.

  3. set the flag LC_MEM_ON_HEAP if your environment only has a limited stack size. When set, functions with large memory requirements use the heap instead of the stack for this memory. The maximum stack size used by a function is 2048 bytes and is verified by a compiler check.

An example on the approach is given with the Linux kernel support found in the directory linux_kernel.

Linux Kernel

The leancrypto library is intended to provide the identical services for user space as well as Linux kernel space. This shall allow developers to only have one crypto provider which they need to maintain and learn to develop with.

The user space and kernel space versions of leancrypto are fully independent of each other. Neither requires the presence of the other for full operation.

Leancrypto therefore can be compiled into a separate Linux kernel module called leancrypto.ko.

Building

In the linux_kernel directory, the support for building the leancrypto library is provided. To build the leancrypto Linux kernel module, use the Makefile in that directory:

  1. make

  2. the leancrypto library is provided with leancrypto.ko

Test Modules

In addition to the leancrypto.ko kernel module, a large number of additional kernel modules are compiled. They are all test modules for regression testing and are not required and even not intended for production use. Insert the kernel modules and check dmesg for the results. Unload the kernel modules afterwards.

The test modules almost all are the user space test application the meson test framework uses too, but compiled into kernel modules. They invoke the leancrypto API to demonstrate that the identical code is supported in user as well as user space.

In addition to the standard leancrypto test code, the following test modules are provided to validate the leancrypto integration into the kernel crypto API:

  • leancrypto_kernel_aead_ascon_tester.ko invokes the Linux kernel crypto API of type skcipher to perform a Ascon and Ascon-Keccak encryption / decryption operation.

  • leancrypto_kernel_ascon_tester.ko invokes the Linux kernel crypto API of type shash to perform a Ascon 128 and Ascon 128a message digest calculation.

  • leancrypto_kernel_dilithium*_tester.ko invokes the Linux kernel crypto API of type akcipher to perform a FIPS 204 (CRYSTALS Dilithium) signature generation and verification.

  • leancrypto_kernel_sphincs_shake_*_tester.ko invokes the Linux kernel crypto API of type akcipher to perform a FIPS 205 (Sphincs Plus) signature generation and verification.

  • leancrypto_kernel_kmac_tester.ko invokes the Linux kernel crypto API type shash to invoke KMAC256 XOF, a keyed message digest using FIPS 202 defined in SP800-185.

  • leancrypto_kernel_kyber*_tester.ko tests the Linux kernel crypto API type kpp to invoke FIPS 203 (CRYSTALS Kyber) key generation, encapsulation and decapsulation.

  • leancrypto_kernel_rng_tester.ko invokes the Linux kernel crypto API type rng to utilize the XDRBG256 deterministic random number generator.

  • leancrypto_kernel_sha3_tester.ko performs the testing of leancrypto’s SHA-3 implementation which is registered as a shash.

Leancrypto Registered with the Linux Kernel Crypto API

The leancrypto.ko offers its own API interface as discussed above. In addition, it registers a subset of algorithms with the kernel crypto API to allow other kernel users, that already use the kernel crypto API for its purposes, to use the algorithms of the leancrypto library without further changes. All algorithms adhere to the kernel crypto API standards and should be usable out of the box.

For the CRYSTALS Kyber support, some special precautions need to be applied considering that there are two modes of operation a user must be aware of: acting as an Initiator or a Responder of a Kyber key agreement. This consideration is identical to the one that needs to be applied for (EC)Diffie-Hellman. The following listing enumerates the call sequence the user must apply for the given mode. The following sequences for both, the initiator and the responder is implemented in leancrypto_kernel_kyber_tester.c as a reference.

  • Acting as Initiator of a Kyber KEM operation:

    1. Generate new keypair: crypto_kpp_set_secret(tfm, NULL, 0); Note, it is permissible to also set an externally-provided key here.

    2. Get public key: crypto_kpp_generate_public_key(req->src = NULL, req->dst = PK)

    3. Send the Kyber PK to the responder and retrieve the Kyber CT from the responder.

    4. Calculate shared secret: crypto_kpp_compute_shared_secret(req->src = CT, req->dst = SS)

  • Acting as Responder of a Kyber KEM operation:

    1. Generate new keypair: crypto_kpp_set_secret(tfm, NULL, 0); Note, it is permissible to also set an externally-provided key here.

    2. Get the initiator PK to generate the CT and shared secret: crypto_kpp_generate_public_key(req->src = PK, req->dst = CT)

    3. Send CT to the initiator

    4. Get the shared secret that was already calculated in step 2: crypto_kpp_compute_shared_secret(req->src = NULL, req->dst = SS)

Please note that the leancrypto Kyber support allows specifying arbitrary sizes of the shared secret (referenced as SS above). When the caller specifies a length that is not equal to 32 bytes, the leancrypto built-in KDF is applied to generate the shared secret of appropriate size.

Leancrypto Kernel Support Configuration

The kernel-compilation of leancrypto is equally flexible as the user space part and thus can still be called “lean”. It allows at compile time to enable or disable algorithms as needed.

Unfortunately, the Linux kernel build system’s graphical configuration tools cannot be used for out-of-tree modules. Thus, if changes to the set of algorithms is intended, the file Kbuild.config must be modified as follows:

The file Kbuild.config contains a configuration of the services. Simply comment out the respective symbols that are not desired to be present. The Kbuild.config file contains a description of each option including its dependencies, if any. You MUST adhere to the specified dependencies as otherwise the compilation will fail due to missing symbols.

Cryptographic Algorithms

Leancrypto offers various cryptographic algorithms:

  • Authenticated Encryption with Associated Data

    • Ascon 128 AEAD and Ascon 128a AEAD

    • Ascon Keccak 256 and 512 AEAD, see Ascon-Keccak for full specification

    • cSHAKE-based AEAD algorithm - algorithm devised with leancrypto, see cSHAKE-AEAD for full specification

    • hash-based AEAD algorithm - algorithm devised with leancrypto, see hash_crypt.c for full specification

    • KMAC-based AEAD algorithm - algorithm devised with leancrypto, see KMAC-AEAD for full specification

    • AES-based AEAD algorithm using SHA2 - see symhmac_crypt.c for full specification

    • AES-based AEAD algorithm using Keccak-based KMAC - see symkmac_crypt.c for full specification

  • Pseudo Random Number Generators

  • Message Digest algorithms

    • SHA2-256, SHA2-512

    • SHA3-224, SHA3-256, SHA3-384, SHA3-512

    • SHAKE-128, SHAKE-256

    • cSHAKE-128, cSHAKE-256

    • Ascon 128 / 128a

    • Ascon XOF / XOFa

  • Keyed Message Digest algorithms

    • HMAC

    • KMAC

  • Key Derivation Functions

    • HKDF

    • SP800-108 KDF (counter, feedback, double pipelining mode)

    • PBKDF2

  • Key Encapsulation Mechanism

  • One Time Pad algorithms

    • HOTP

    • TOTP

  • Signature algorithm

    • ML-DSA (Dilithium) including HashML-DSA

    • ML-DSA (Dilithium) hybrid signature operation with Curve25519

    • SLH-DSA (Sphincs+) including HashSLH-DSA

  • Symmetric algorithms

    • AES: ECB, CBC, CTR, KW

    • ChaCha20

Leancrypto API Documentation

Doxygen Documentation

The Doxygen Documentation is automatically generated during the compilation of the source code if the doxygen binary is found on the host system.

API Documentation in Header Files

The leancrypto API is documented in the exported header files. The only header file that needs to be included in the target code is #include <leancrypto.h>. This header file includes all algorithm-specific header files for the compiled and supported algorithms.

To fully understand the API, please consider the following base concept of leancrypto: Different algorithm implementations are accessible via common APIs. For example, different random number generator algorithms are accessible via the RNG API. To ensure the common APIs act on the proper algorithm, the caller must use algorithm-specific initialization functions. The initialization logic returns a “cipher handle” that can be used with the common API for all subequent operations.

The various header files contain data structures which are provided solely for the purpose that appropriate memory on stack can be allocated. These data structures do not consititute an API in the sense that calling applications should access member variables directly. If access to member variables is desired, proper accessor functions are available. This implies that changes to the data structures in newer versions of the library are not considered as API changes!

The following list enumerates all algorithm-specific header files which contains the respective API documentation:

Example Code

Almost all test cases found in the various tests directories use the aforementioned public APIs and thus serve as example code for the given algorithms.

Debugging Support

The leancrypto library offers various types of debugging support outlined in the following sections.

Kyber / Dilithium: Print Results of Intermediate Calculation Steps

An implementation that is compliant with the NIST implementation that complies with FIPS 203 draft as well as additional changes expressed by NIST at the PQC-Forum is provided with leancrypto. It allows developers to compile both Kyber and Dilithium in a debug mode where the calculation results of each step of the key generation, Kyber encapsulation and decapsulation, as well as the Dilithium signature generation and verification can be displayed. This allows other developers to compare their implementation to match with leancrypto. The following steps have to be taken to obtain the debug output after fetching the library from the provided link and making sure the meson build system is available:

Kyber:

  1. Setup of the build directory: meson setup build

  2. Configure Kyber debug mode: meson configure build -Dkyber_debug=enabled

  3. Compile the code: meson compile -C build

  4. Execute the test tool providing the output of Kyber, ML-KEM-1024: build/kem/tests/kyber_kem_tester_c

  5. Execute the test tool providing the output of Kyber, ML-KEM-768: build/kem/tests/kyber_768_kem_tester_c

  6. Execute the test tool providing the output of Kyber, ML-KEM-512: build/kem/tests/kyber_512_kem_tester_c

Dilithium:

  1. Setup of the build directory (if it was not already set up for the Kyber tests): meson setup build

  2. Configure Dilithium debug mode: meson configure build -Ddilithium_debug=enabled`

  3. Compile the code: meson compile -C build

  4. Execute the test tool providing the output of Dilithium, ML-DSA-87: build/signature/tests/dilithium_tester_c

  5. Execute the test tool providing the output of Dilithium, ML-DSA-65: build/signature/tests/dilithium_65_tester_c

  6. Execute the test tool providing the output of Dilithium, ML-DSA-44: build/signature/tests/dilithium_44_tester_c

The test tool outputs is segmented into the key generation steps, Dilithium signature generation and verification steps, as well as Kyber encapsulation and decapsulation steps. The output specifies the mathematical operation whose result is shown. When displaying the output of a vector, one line is used. When displaying a matrix, the output of one row of the matrix is displayed per line. This implies that as many lines are printed as rows are present in the matrix.

During the course of the development of both Kyber and Dilithium reference implementations, NIST developers reached out to compare intermediate results of both algorithms with the ones produced by leancrypto. The debug logging information was used as a basis for the discussion with the NIST development team to verify that both implementations i.e. the NIST reference implementation as well as leancrypto, correspond.

Side-Channel Analysis

Side channels is a recurring problem which can inadvertently leak sensitive data where the leak may be visible not just locally, but possibly also remotely. Thus, finding side channels based on sensitive data is important.

The leancrypto library has built-in support for finding side-channels (or the lack thereof) by marking memory holding sensitive data and using Valgrind to identify any possible side channels. The concept is summarized on the Timecop web page as follows:

Even though modern CPUs and operating systems have various methods to separate processes from one another, some side-channels can remain that allow attackers to extract information across process, CPU, or even network boundaries.

One such side-channel can open up when the execution time of a piece of code depends on secret data. This class of vulnerabilities has been used succesfully in the past to extract encryption keys from AES, private keys from RSA, and other kinds of attacks.

Timing side-channels can be hard to spot in the wild, but they can be detected automatically to some degree with dynamic analysis.

How it works

Most timing side-channels are rooted in one of the following three causes:

  • Conditional jumps based on secret data [1] e.g. if (key[i] == 0)

  • Table lookups at secret indices [2], [3], [4], [5] e.g. s[i] = substitution_table[key[i]]

  • Variable-time CPU instructions operating on secret data [6], e.g. key[i] / c On Intel Pentium 4, the number of cycles for a division instruction depends on the arguments.

Adam Langley described in 2010 how the first two types can be detected automatically using Valgrind.

Valgrind is a framework for dynamic code analysis that comes with a large range of tools for specific analysis tasks. One of those tools checks memory usage to identify memory leaks, use of uninitialized memory, read after free, and other common problems related to memory management.

When Valgrind checks for the use of uninitialized memory, it performs exactly the checks necessary to spot timing side-channels. By flagging secret data as uninitialized for Valgrind, it will report any cases where conditional jumps or table lookups are based on secret data.

Limitations

Valgrind cannot spot cases where variable-time code is caused by variable-time CPU instructions.

Testing Instructions

To perform such a side channel analysis, apply the following steps:

  1. Configure leancrypto with the following option: meson configure build -Dtimecop=enabled

  2. Compile the code

  3. Execute different test cases with Valgrind as follows: valgrind --track-origins=yes build/kem/tests/kyber_kem_tester_common

  4. A side channel is present if Valgrind reports an issue like the following where it reports a “Conditional jump or move depends on uninitialised value(s)” based on “Uninitialised value was created by a client request”:

==13317== Conditional jump or move depends on uninitialised value(s)
==13317==    at 0x4851A2E: bcmp (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==13317==    by 0x10A86F: lc_compare (../internal/src/compare.c:52)
==13317==    by 0x10A6A8: _kmac_256_tester (../kmac/tests/kmac_256_tester.c:912)
==13317==    by 0x10A410: kmac_tester (../kmac/tests/kmac_256_tester.c:942)
==13317==    by 0x10A410: main (???:956)
==13317==  Uninitialised value was created by a client request
==13317==    at 0x48A0E7A: lc_kmac_init (../kmac/src/kmac.c:119)
==13317==    by 0x10A665: _kmac_256_tester (../kmac/tests/kmac_256_tester.c:909)
==13317==    by 0x10A410: kmac_tester (../kmac/tests/kmac_256_tester.c:942)
==13317==    by 0x10A410: main (???:956)

References

[1] Onur Acıiçmez, Çetin Kaya Koç, Jean-Pierre Seifert, Predicting secret keys via branch prediction. In Proceedings of the 7th Cryptographers’ Track at the RSA Conference on Topics in Cryptology

[2] Yuval Yarom, Katrina Falkner, FLUSH+RELOAD: a High Resolution, Low Noise, L3 Cache Side-Channel Attack.

[3] Daniel J. Bernstein, Cache-timing attacks on AES.

[4] Paul C. Kocher, Timing Attacks in Implementations of Diffie-Hellman, RSA, DSS, and Other Systems.

[5] Mehmet Sinan İnci, Berk Gülmezoğlu, Gorka Irazoqui, Thomas Eisenbarth, Berk Sunar, Seriously, get off my cloud! Cross-VM RSA Key Recovery in a Public Cloud.

[6] Thierry Kaufmann, Hervé Pelletier, Serge Vaudenay, and Karine Villegas When Constant-time Source Yields Variable-time Binary: Exploiting Curve25519-donna Built with MSVC 2015.

CAVP Certificates

The leancrypto library is tested with the NIST ACVP framework and received the following certificates.

The testing was conducted using the ACVP Parser.

Version 1.1.0

leancrypto CAVP Certificates

Version 1.0.1

leancrypto CAVP certificates

Version 1.0.0

This version obtained the first ever ML-DSA and ML-KEM CAVP certificates!

leancrypto CAVP certificates

Version 0.8.0

Version 0.7.0

Version 0.6.0

Papers

The following table present papers written for various topics.

Link Abstract
Kyber and TLS This document outlines the shortcomings of a current proposal to add CRYSTALS Kyber into TLS and proposes an alternative solution.
KyberIES Specification This document provides the specification of Kyber Integrated Encryption Schema (IES) conceptually similar to ECIES.
Kyber KEX 2-way Approach This document provides the specification of Kyber Key Exchange (KEX) with integrated authentication that can serve as a Diffie-Hellman drop-in replacement.
AEAD algorithm based on KMAC or cSHAKE This document provides the specification of the cryptographic algorithm following the Authenticated Encryption with Additional Data (AEAD) approach using KMAC and cSHAKE.
Hybrid KEM Specification This document specifies the Hybrid KEM cryptographic algorithm combining Kyber and X25519.
Deterministic RNG Based on cSHAKE and KMAC This specification defines a simple deterministic random number generator (DRNG) which can be used to generate cryptographically secure random bit strings for various use cases including symmetric and asymmetric key generation services. The DRNG is based on either cSHAKE or KECCAK Message Authentication Code (KMAC) and is intended to support a wide range of applications and requirements, and is conservative in its resource consumption.
XDRBG Specification The document provides a specification of a deterministic random bit generator (DRBG) based on extensible output functions (XOF). It includes a security proof.
Ascon-Keccak Specification The document provides a specification of Ascon using the Keccak sponge to provide an AEAD algorithm with 256 and 512 bit classic security strength or 128 and 256 bit quantum security strength. The specification is also published at IACR.

XDRBG

The XDRBG is a random number generator using the SHAKE cryptographic primitive.

Algorithm Specification

The algorithm specification as publised at the ToSC 2024 conference.

The XDRBG specification provides the algorithm definition of the XDRBG along with the security proof. An updated version of the paper with the AIS 20/31 definition will be released soon. In addition, the XDRBG presentation provides a brief overview.

Source Code

The source code is available at the Github repository. The source code shows that XDRBG is lean compared to other deterministic random number generators. In addition, the code contains various tests to demonstrate the correctness of the implementation.

The XDRBG is also the default deterministic random number generator in leancrypto. The implementation of XDRBG in leancrypto uses accelerated Keccak primitives. The test harness executed with meson test also provides performance data for generating 1GBytes of data which can be compared to other deterministic random number generators offered by leancrypto.

About This Site

Code Signing Certificate

All source code distributed on this web site is signed. In order to verify the signature and thus the integrity and authenticity of the obtained code, use the following command:

1
gpg --verify leancrypto-*.tar.xz.asc leancrypto-*.tar.xz

This command only performs the verification if the associated public key was previously imported into the key ring. In case the public key needs to be imported, use the following command which imports the key from 2024:

1
curl https://leancrypto.org/about/smuellerDD-2024.asc | gpg --import

The following public keys are available: