The ESDM export interfaces that allow obtaining random numbers from a fully seeded DRNG as specified in crypto/esdm.h. By using the interface function esdm_get_random_bytes_full, the ESDM is registered as a random number generator with the kernel crypto API's RNG framework. This registered RNG provides random numbers from an always appropriately seeded and initialized DRNG. When a caller performs a crypto_rng_reset() call on the ESDM, the ESDM injects the provided data into the auxiliary pool and flags a reseed. This reseed is performed by the immediate subsequent DRNG generation operation. The RNG registered by the ESDM with the kernel crypto API is accessible via the name "esdm". In addition, the ESDM is registered as "stdrng" with the highest priority which implies that the kernel crypto API call of crypto_get_default_rng accesses the ESDM. The ESDM is marked as fips_allowed = 1 in the testmgr because it complies with the FIPS 140 rules as follows: - SP800-90A: The ESDM uses the kernel crypto API's DRBG and thus provides access to a fully seeded and SP800-90A DRBG. - SP800-90B: The ESDM manages entropy sources via its plugins. Currently there is no internal entropy source provided which means that the used entropy sources must provide their own SP800-90B analysis. For the Jitter RNG, a separate SP800-90B analysis is provided. The ESDM only ensures that the Jitter RNG is appropriately initialized before it is used as an entropy source. The kernel RNG (random.c) entropy source on the other hand is not SP800-90B compliant. Thus, in FIPS mode, the ESDM credits its data with zero bits of entropy. - SP800-90C: The ESDM follows the current draft of SP800-90C when compiled with the option CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES. The DRBG is initially seeded with at least 384 bits of entropy before it is marked as fully seeded (and thus produces random numbers via the esdm_get_random_bytes_full call. Subsequent reseeds are performed with at least 256 bits of entropy. The conditioning operation performed in the auxiliary pool requires 64 more bits of entropy to be fed into the conditioner function provide the respective entropy output (e.g. 256 bits of entropy are fed into the SHA-256 conditioner resulting in the output of 192 bits of entropy provided by the entropy source to the ESDM). With the given entropy sources, the ESDM follows the RBG2(NP) construction method. Signed-off-by: Stephan Mueller <smueller@xxxxxxxxxx> --- crypto/esdm/Kconfig | 14 +++++ crypto/esdm/Makefile | 2 + crypto/esdm/esdm_drng_kcapi.c | 1 + crypto/esdm/esdm_interface_kcapi.c | 91 ++++++++++++++++++++++++++++++ crypto/testmgr.c | 8 +++ 5 files changed, 116 insertions(+) create mode 100644 crypto/esdm/esdm_interface_kcapi.c diff --git a/crypto/esdm/Kconfig b/crypto/esdm/Kconfig index 43e11484e95c..3636c1c79602 100644 --- a/crypto/esdm/Kconfig +++ b/crypto/esdm/Kconfig @@ -27,6 +27,20 @@ config CRYPTO_ESDM_SHA256 bool default y if CRYPTO_LIB_SHA256 +menu "ESDM Interfaces" + +config CRYPTO_ESDM_KCAPI_IF + tristate "Interface with Kernel Crypto API" + depends on CRYPTO_RNG + help + The ESDM can be registered with the kernel crypto API's + random number generator framework. This offers a random + number generator with the name "esdm" and a priority that + is intended to be higher than the existing RNG + implementations. + +endmenu # "ESDM Interfaces" + menu "Specific DRNG seeding strategies" config CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES diff --git a/crypto/esdm/Makefile b/crypto/esdm/Makefile index 404436de0aa2..0bf8d65dd5fa 100644 --- a/crypto/esdm/Makefile +++ b/crypto/esdm/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_CRYPTO_ESDM_DRNG_KCAPI) += esdm_drng_kcapi.o obj-$(CONFIG_CRYPTO_ESDM_KERNEL_RNG) += esdm_es_krng.o obj-$(CONFIG_CRYPTO_ESDM_JENT) += esdm_es_jent.o + +obj-$(CONFIG_CRYPTO_ESDM_KCAPI_IF) += esdm_interface_kcapi.o diff --git a/crypto/esdm/esdm_drng_kcapi.c b/crypto/esdm/esdm_drng_kcapi.c index ae8d2be91b37..03135337196b 100644 --- a/crypto/esdm/esdm_drng_kcapi.c +++ b/crypto/esdm/esdm_drng_kcapi.c @@ -99,6 +99,7 @@ static void *esdm_kcapi_drng_alloc(u32 sec_strength) } if (!memcmp(drng_name, "stdrng", 6) || + !memcmp(drng_name, "esdm", 4) || !memcmp(drng_name, "jitterentropy_rng", 17)) { pr_err("Refusing to load the requested random number generator\n"); return ERR_PTR(-EINVAL); diff --git a/crypto/esdm/esdm_interface_kcapi.c b/crypto/esdm/esdm_interface_kcapi.c new file mode 100644 index 000000000000..f2968d83c991 --- /dev/null +++ b/crypto/esdm/esdm_interface_kcapi.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * ESDM interface with the RNG framework of the kernel crypto API + * + * Copyright (C) 2022, Stephan Mueller <smueller@xxxxxxxxxx> + */ + +#include <crypto/esdm.h> +#include <linux/module.h> +#include <crypto/internal/rng.h> + +#include "esdm_drng_mgr.h" +#include "esdm_es_aux.h" + +static int esdm_kcapi_if_init(struct crypto_tfm *tfm) +{ + return 0; +} + +static void esdm_kcapi_if_cleanup(struct crypto_tfm *tfm) { } + +static int esdm_kcapi_if_reseed(const u8 *src, unsigned int slen) +{ + int ret; + + if (!slen) + return 0; + + /* Insert caller-provided data without crediting entropy */ + ret = esdm_pool_insert_aux((u8 *)src, slen, 0); + if (ret) + return ret; + + /* Make sure the new data is immediately available to DRNG */ + esdm_drng_force_reseed(); + + return 0; +} + +static int esdm_kcapi_if_random(struct crypto_rng *tfm, + const u8 *src, unsigned int slen, + u8 *rdata, unsigned int dlen) +{ + int ret = esdm_kcapi_if_reseed(src, slen); + + if (!ret) + esdm_get_random_bytes_full(rdata, dlen); + + return ret; +} + +static int esdm_kcapi_if_reset(struct crypto_rng *tfm, + const u8 *seed, unsigned int slen) +{ + return esdm_kcapi_if_reseed(seed, slen); +} + +static struct rng_alg esdm_alg = { + .generate = esdm_kcapi_if_random, + .seed = esdm_kcapi_if_reset, + .seedsize = 0, + .base = { + .cra_name = "stdrng", + .cra_driver_name = "esdm", + .cra_priority = 500, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_init = esdm_kcapi_if_init, + .cra_exit = esdm_kcapi_if_cleanup, + + } +}; + +static int __init esdm_kcapi_if_mod_init(void) +{ + return crypto_register_rng(&esdm_alg); +} + +static void __exit esdm_kcapi_if_mod_exit(void) +{ + crypto_unregister_rng(&esdm_alg); +} + +module_init(esdm_kcapi_if_mod_init); +module_exit(esdm_kcapi_if_mod_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller <smueller@xxxxxxxxxx>"); +MODULE_DESCRIPTION("Entropy Source and DRNG Manager kernel crypto API RNG framework interface"); +MODULE_ALIAS_CRYPTO("esdm"); +MODULE_ALIAS_CRYPTO("stdrng"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 2ce698eb14b6..0865105f9377 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4878,6 +4878,14 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .akcipher = __VECS(ecrdsa_tv_template) } + }, { + .alg = "esdm", + .test = alg_test_null, +#ifdef CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES + .fips_allowed = 1, +#else + .fips_allowed = 0, +#endif }, { .alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)", .test = alg_test_aead, -- 2.33.1