SkillAgentSearch skills...

Libdrbg

A portable library implementing NIST SP 800-90A DRBGs

Install / Use

/learn @ANSSI-FR/Libdrbg
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

compilation

libdrbg project

Copyright (C) 2022

This software is licensed under dual BSD and GPL v2 licenses.

2025-11-25: ANSSI has stopped working on the project. Interested people can use the maintained fork at https://github.com/libecc/libdrbg.

Authors

Description

This software implements DRBG (Deterministic Random Bit Generators) as specified in the NIST Special Publication 800-90A standard. Namely, it implements the three standardized variants:

  • <ins>Hash-DRBG</ins>: DRBG based on hash functions.
  • <ins>HMAC-DRBG</ins>: DRBG based on HMAC.
  • <ins>CTR-DRBG</ins>: DRBG based on block ciphers in counter mode.

The current implementations of Hash-DRBG and HMAC-DRBG go beyond the strict list of the specified hash functions in the standard (only SHA-{1,224,256,384,512,512-224,512-256} are allowed in the standard): they accept any of the following hash functions - or HMAC based on them - that are implemented in the internal libhash subproject:

  • SHA-{224,256,384,512,512-224,512-256}, SHA-3-{224,256,384,512}, RIPEMD-160, SM3, STREEBOG-{256,512} (RFC 6986), SHAKE-256 (with 114 bytes output), BELT-HASH (STB 34.101.31-2011), BASH-{224,256,384,512} (STB 34.101.77-2020).
  • Deprecated hash functions: SHA-{0,1}, MD-{2,4,5}, MDC2, GOST34-11-94.

NOTE: please consider the deprecated hash functions with care, as they are mainly here for compatibility and tests reasons. By default, the strict NIST mode is activated meaning that only SHA-{1,224,256,384,512,512-224,512-256} hash functions are activated during compilation. It is possible to force the strict NIST mode using STRICT_NIST_SP800_90A=1 or to force its deactivation with the STRICT_NIST_SP800_90A=0 toggle during compilation. Beware that SHA-1 is in the list of the available hashes for conformance with the standard but should not be used as it is deprecated and broken by practical collision attacks.

The implementation of CTR-DRBG strictly conforms to the standard as only AES and TDEA (TDES) are supported as possible block ciphers, although it would be possible to (easily) expand the library with other block ciphers. Please note that TDEA is in the process of being fully deprecated, hence AES is the only choice in practice for production code.

All the variants of the NIST standard should be implemented and selectable through options: with Prediction Resistance or not, with DF or not, etc. This exhaustive compatibility has been one of the leitmotivs of developing the library as we have not found small, portable and complete implementations in C (one of the most complete implementations is in the Linux kernel but its adherence to external modules makes it hard to be used in a standalone fashion).

The source code is pure C-99 only using stdint.h (mainly for uint with strict sizes types), stdbool.h (for booleans), and basic stdlib.h (mainly for memcpy, memset and memcmp). It should be compatible with any decent C (or C++) compiler, and portable across platforms as no external dependency is needed. No allocation is used across the project, which makes it suitable for embedded contexts. Finally, printf is used but only in the tests and main files using the DRBG API: the core files and algorithms do not use it.

The source code aims at being portable and compatible with as many platforms as possible, but the low-level primitive APIs should be simple enough and self-explanatory to replace the underlying algorithms with assembly optimized and/or hardware accelerated alternatives. For instance on recent Intel and AMD x86 platforms, the AES encryption core in aes/aes.c can be replaced with AES-NI instructions to accelerate the CTR-DRBG backend, and the SHA-{1,224,256} in libhash can be replaced with Intel SHA extensions to accelerate the Hash-DRBG and HMAC-DRBG backends.

Compiling

Compiling is as simple as:

<pre> $ make </pre>

Some options can be provided in the form of toggles:

  • STRICT_NIST_SP800_90A=0 will deactivate the strict mode for the hash functions. When WITH_HASH_CONF_OVERRIDE is not used (see below), the NIST approved hash functions are selected for compilation, and checked at runtime (namely SHA-1, SHA-224, SHA-512-224, SHA-256, SHA-512-256, and SHA-512).
  • SMALL_MEMORY_FOOTPRINT=1 will use small footprint implementations, this mostly concerns AES where table based or compact SBOX variants are selected.
  • VERBOSE=1 will activate self-tests verbosity.
  • USE_SANITIZERS=1 will compile with the sanitizers (address, undefined behaviour, leak). This is useful for checks before shipping production code, but usually heavily impacts performance and hence should be deactivated when not debugging. However, if performance is not an issue, it is advised to leave them as they will catch (potentially dangerous) runtime errors.
  • PEDANTIC=1 allows to activate strict(er) compilation flags (by default the usual -Wall -Wextra -Wunreachable-code -Werror is used, this activates more picky options).
  • WNOERROR=1 will force compilation without the -Werror flag, i.e. compiler warning are not treated as errors (this can be useful for cases where some warnings are false alarms or for toolchains with picky warnings).
  • WITH_TEST_ENTROPY_SOURCE=1 activates a default entropy backend depending on the OS (/dev/random on UNIX based including MacOS, crypto provider under Windows). See entropy.c for more details. These implementations are examples, and you are encouraged to add more entropy sources to improve them (see the discussion below).
  • NO_XXX_DRBG=1 is used to remove a specific DRBG backend (where XXX is one of HASH, HMAC or CTR). More than one toggle can be specified, but beware that removing the three backends all together will trigger a compilation error.
  • NO_BC_TDEA=1 and/or NO_BC_AES=1 are used to remove TDEA and AES algorithms when they are not necessary (i.e. the user wants to use the CTR-DRBG without one of the algorithms). Beware that removing both TDEA and AES will render the CTR-DRBG unusable.
  • DEBUG=1 activates the -g options to embed the symbols and make debugging sessions easier (should not be activated for production code).
  • WITH_HASH_CONF_OVERRIDE is used to select an explicit subset of the hash functions, see below for more details. Beware that using this flag will override the NIST strict hash functions list in any case, but if the strict mode is active checks will be performed at runtime (meaning that only the subset of hash functions present in WITH_HASH_CONF_OVERRIDE and conforming to the standard will be accepted, the others will trigger an error).
  • GCC_ANALYZER=1 is used to activate the gcc static analyzer. This is only relevant for gcc versions >= 10 (where this static analyzer has been introduced).

It is possible to provide (cross-)compilation options using the toggles:

  • CC=XXX that will use the XXX compiler.
  • CROSS_COMPILE=YYY that will use the YYY prefix for a toolchain (e.g. arm-none-eabi-).
  • EXTRA_CFLAGS=ZZZ will add additional user defined CFLAGS.

For example, the following invocation will compile the project using the sparc64-linux-gnu- toolchain and produce a static ELF binary (that it will be possible to emulate with qemu-user for instance):

<pre> $ make clean && CROSS_COMPILE=sparc64-linux-gnu- CC=gcc WITH_TEST_ENTROPY_SOURCE=1 VERBOSE=1 EXTRA_CFLAGS="-static" make </pre>

WITH_TEST_ENTROPY_SOURCE=1 activates the default entropy source on the OS (as we use a Linux based toolchain, /dev/random is used) and VERBOSE=1 activates verbose self-tests. Note that the same compilation could have been equally performed with CC=sparc64-linux-gnu-gcc.

Another example of coss-compilation is for Windows using the MinGW toolchain:

<pre> $ make clean && WNOERROR=1 CROSS_COMPILE=i686-w64-mingw32- CC=gcc WITH_TEST_ENTROPY_SOURCE=1 EXTRA_CFLAGS="-static" make </pre>

As we target embedded and constrained platforms, we also provide ways to only embed a subset of the hash functions in order to decrease the (flash) memory footprint:

  • The libhash/libhash_config.h configuration file where it is possible to only select the needed hash functions.
  • The more convenient WITH_HASH_CONF_OVERRIDE toggle can be used when compiling to tune the hash functions list to be embedded. Remember to deactivate the NIST strict mode with STRICT_NIST_SP800_90A=0 when hash functions not approved by the standard are selected.

For example, the following invocation will only select SHA-256 and SHA-3-256 (note the STRICT_NIST_SP800_90A=0 as SHA-3-256 is not in the standard approved list):

<pre> $ STRICT_NIST_SP800_90A=0 WITH_HASH_CONF_OVERRIDE="-DWITH_HASH_CONF_OVERRIDE -DWITH_HASH_SHA256 -DWITH_HASH_SHA3_256" make </pre>

NOTE: please beware that when selecting specific hash functions, it is still possible to ask

Related Skills

View on GitHub
GitHub Stars18
CategoryDevelopment
Updated4mo ago
Forks10

Languages

C

Security Score

92/100

Audited on Dec 3, 2025

No findings