Subsections of Leancrypto
Sources
Github.com
leancrypto is developed at its Github repository.
Releases
Releases of leancrypto are avaiable at the release page as well as at the Github release site.
Releases
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
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
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:
-
Setup: meson setup build
-
Compile: meson compile -C build
-
Test: meson test -C build
-
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
:
-
cd linux_kernel
-
make
-
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:
-
Adjust the build system as needed to compile and link it
-
Adjust the file ext_headers.h
to point to the right header files and
locations.
-
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:
-
make
-
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.
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
-
Keyed Message Digest algorithms
-
Key Derivation Functions
-
Key Encapsulation Mechanism
-
One Time Pad algorithms
-
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.
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.
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:
-
Setup of the build directory: meson setup build
-
Configure Kyber debug mode: meson configure build -Dkyber_debug=enabled
-
Compile the code: meson compile -C build
-
Execute the test tool providing the output of Kyber, ML-KEM-1024: build/kem/tests/kyber_kem_tester_c
-
Execute the test tool providing the output of Kyber, ML-KEM-768: build/kem/tests/kyber_768_kem_tester_c
-
Execute the test tool providing the output of Kyber, ML-KEM-512: build/kem/tests/kyber_512_kem_tester_c
Dilithium:
-
Setup of the build directory (if it was not already set up for the Kyber tests): meson setup build
-
Configure Dilithium debug mode: meson configure build -Ddilithium_debug=enabled`
-
Compile the code: meson compile -C build
-
Execute the test tool providing the output of Dilithium, ML-DSA-87: build/signature/tests/dilithium_tester_c
-
Execute the test tool providing the output of Dilithium, ML-DSA-65: build/signature/tests/dilithium_65_tester_c
-
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:
-
Configure leancrypto with the following option: meson configure build -Dtimecop=enabled
-
Compile the code
-
Execute different test cases with Valgrind as follows: valgrind --track-origins=yes build/kem/tests/kyber_kem_tester_common
-
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