Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1951038pxb; Sat, 27 Feb 2021 05:47:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJztzeo28FzFAb6NPeW8mQyFrtin8U9kak4EydrdwtF0dtj8t7hPtRY1KBgioyYIoCCYC/ZX X-Received: by 2002:a17:906:c08e:: with SMTP id f14mr8347608ejz.388.1614433636270; Sat, 27 Feb 2021 05:47:16 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1614433636; cv=pass; d=google.com; s=arc-20160816; b=jozlo+SlqW1VGu0IWVQ+v5S5zYNh19y4DXQACzL36hm+8b7e1Bmd9xhdPIHJ+ncTG9 9nqhLcCKLlik80HfAg655ZvNjYTHw3bODaqc51wdmZBp/x5Nf91BakOILopdhBKBQJVY Ily42TjQBJu4QWdumr3a6f57eQakx3Pk3ETqMhHlnhXX1jVI+TiZvfRSCnZmZKJHOuNu W1/mAgRuSD3Udf115Z7p9FheyAqmpv9NJ3/1T6UoinFEhqHfmcDvRZAiD5V+ihewF92W rrcGEXlk1O/t2NNVBRyjh8oLvXrhtiTRHzPkI9yeaaqvHP5JF8sWP7iuuC8lTPG7PDn+ SBXw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=o9u1zbioHXlOZoNYXCnstY+KQJcyUg3HLQvx1N5kQCA=; b=C1GQVOpb7MyTN9ti2fL7Xx/ykATekren1Z/hntCsHiaxxMABtnofPU/6vYmGf4gQzX p6W+79/1F2/FKF8piohubHmXCBcUMbU++YTtKWwa58+ge95cjvk6iLZ30ic2dNin7bOv pKLU2vh8paiU9JyzQXHsAonFx2AZJrjX/jQ9azVo+2/XIl1dedn+T95cNM+dMTGlYRPD 9ZcGCUoNbiFXsjVpu5DD3zmy9cXjkMRoMD7KcgYXGZvgFRF1sVjcQ0eEDDHo5rw4p2Mj /N/8b6zlqoLf6LYEk3FYO5N7dJhCWapZABQRexJttxAGVnag3cqD1kLTHBZDqOpsBwKZ yJfg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@chronox.de header.s=strato-dkim-0002 header.b=mjcu8uEa; arc=pass (i=1); spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i17si7349589ejr.455.2021.02.27.05.46.53; Sat, 27 Feb 2021 05:47:16 -0800 (PST) Received-SPF: pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chronox.de header.s=strato-dkim-0002 header.b=mjcu8uEa; arc=pass (i=1); spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230084AbhB0Npl (ORCPT + 99 others); Sat, 27 Feb 2021 08:45:41 -0500 Received: from mo4-p04-ob.smtp.rzone.de ([85.215.255.123]:32662 "EHLO mo4-p04-ob.smtp.rzone.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230112AbhB0Npc (ORCPT ); Sat, 27 Feb 2021 08:45:32 -0500 ARC-Seal: i=1; a=rsa-sha256; t=1614433251; cv=none; d=strato.com; s=strato-dkim-0002; b=l2MuWJ9Cx6CI3hzWLFJoLMw+k+0SWXaNJcmbed9er3Cb1oYtzOUg96l0VnYhucb+V7 5WHnRox7bWuiPws3rAODceVZp3t+V2zVwAcXAMWMV9A8ZR16QPbfyyq7sa7LTSQBWuR7 3vkImqni69v4t9DL7NR4BYzzaiR+2qyRZN8JmU51eBHUBu6GmNNdKETNnZtJRhM90Ees Vt/uTX6IYIHApOZmE3tqN3kjkUU5pGWjksVY07oO5wBoKw82mdu3FTeT0b2arptr+aBx vbaYC40Q5PpkC8BnVJlmmM5g3SjvlLvoVRDLBGJCN4EdJw9fUfJdF8Y1NNYViPpJrkgS jQAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1614433251; s=strato-dkim-0002; d=strato.com; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=o9u1zbioHXlOZoNYXCnstY+KQJcyUg3HLQvx1N5kQCA=; b=Hc+se9cs2430IstbCWNGhjO6mnAYrS/iAOeC7TMyZH70n+CM1QMj6+Cb/2jOBLnxZs zutZMK+aD1IxCdfRDK17e7X7KFYoBSnpe1OBZU5LqerD/+VV5x6usVRWG3jpzkepRif8 qsVL+VvOXSl4JfDEUhSlHONRzcY27vxK2R9+Fb/3g/iuhVpSKGo+B4YbNJCstphuXrsr R79xbv78rhJ73ZSlDLiSHw/tOsy8QfCsZR3vLDAGkEqBKglmO27VVHdpKoTcs7ROQGB4 aMiIfLgu1fj5XyBJ4AxERkB5eUBxL7VtcIw9n2Osd3QyfH8iL9ePeLGhb7fjwP8j+7R1 TkKA== ARC-Authentication-Results: i=1; strato.com; dkim=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1614433251; s=strato-dkim-0002; d=chronox.de; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=o9u1zbioHXlOZoNYXCnstY+KQJcyUg3HLQvx1N5kQCA=; b=mjcu8uEaQKO6xW7PIY0bACyKdaA8WqVqSJcrF1uFK1zpQnlbbAGYCMkjjxrGcfF7mA 2x30fi3roMTFXsJQsoxVGIIEmxUTIb5JQ/RrsziTLl71ri33ybwiRlso3IsDw93XqaZ+ JUM7JnDnnBasrRPuZ4G1H0c7kM/nuaJP38Z6fiyj2cfknkTwtLnBRded8pylzCtKpwf5 J7Tk8PywgbWsHSlVq+6aalw6PvTtaK02aoo5elu6kdWb69GIHOWco/P06JFvgZTPSBIc P0qy8n9GSDVltD88eod99OgL0EzlwUsNk9b1e4UTqfyH7kpmQONN++PcD7q/9QNNyImR Qztw== Authentication-Results: strato.com; dkim=none X-RZG-AUTH: ":P2ERcEykfu11Y98lp/T7+hdri+uKZK8TKWEqNyiHySGSa9k9xmwdNnzGHXPZIfSc8k+7" X-RZG-CLASS-ID: mo00 Received: from positron.chronox.de by smtp.strato.de (RZmta 47.19.0 DYNA|AUTH) with ESMTPSA id 608030x1RDeoUDD (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Sat, 27 Feb 2021 14:40:50 +0100 (CET) From: Stephan =?ISO-8859-1?Q?M=FCller?= To: Tso Ted , linux-crypto@vger.kernel.org Cc: Willy Tarreau , Nicolai Stange , LKML , Arnd Bergmann , Greg Kroah-Hartman , "Eric W. Biederman" , "Alexander E. Patrakov" , "Ahmed S. Darwish" , Matthew Garrett , Vito Caputo , Andreas Dilger , Jan Kara , Ray Strode , William Jon McCann , zhangjs , Andy Lutomirski , Florian Weimer , Lennart Poettering , Peter Matthias , Marcelo Henrique Cerri , Neil Horman , Randy Dunlap , Julia Lawall , Dan Carpenter , Andy Lavr , Eric Biggers , "Jason A. Donenfeld" , Petr Tesarik , John Haxby Subject: [PATCH v38 08/13] LRNG - add kernel crypto API PRNG extension Date: Sat, 27 Feb 2021 14:37:51 +0100 Message-ID: <5144355.Sb9uPGUboI@positron.chronox.de> In-Reply-To: <3277560.QJadu78ljV@positron.chronox.de> References: <3277560.QJadu78ljV@positron.chronox.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Add runtime-pluggable support for all PRNGs that are accessible via the kernel crypto API, including hardware PRNGs. The PRNG is selected with the module parameter drng_name where the name must be one that the kernel crypto API can resolve into an RNG. This allows using of the kernel crypto API PRNG implementations that provide an interface to hardware PRNGs. Using this extension, the LRNG uses the hardware PRNGs to generate random numbers. An example is the S390 CPACF support providing such a PRNG. The hash is provided by a kernel crypto API SHASH whose digest size complies with the seedsize of the PRNG. CC: Torsten Duwe CC: "Eric W. Biederman" CC: "Alexander E. Patrakov" CC: "Ahmed S. Darwish" CC: "Theodore Y. Ts'o" CC: Willy Tarreau CC: Matthew Garrett CC: Vito Caputo CC: Andreas Dilger CC: Jan Kara CC: Ray Strode CC: William Jon McCann CC: zhangjs CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Roman Drahtm=FCller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman Signed-off-by: Stephan Mueller =2D-- drivers/char/lrng/Kconfig | 13 ++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_kcapi.c | 225 +++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi.c diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig index 0b94a96e4729..f16bd237ab9e 100644 =2D-- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -141,6 +141,19 @@ config LRNG_DRBG Enable the SP800-90A DRBG support for the LRNG. Once the module is loaded, output from /dev/random, /dev/urandom, getrandom(2), or get_random_bytes_full is provided by a DRBG. + +config LRNG_KCAPI + tristate "Kernel Crypto API support for the LRNG" + depends on CRYPTO + depends on !LRNG_DRBG + select CRYPTO_RNG + select LRNG_KCAPI_HASH + help + Enable the support for generic pseudo-random number + generators offered by the kernel crypto API with the + LRNG. Once the module is loaded, output from /dev/random, + /dev/urandom, getrandom(2), or get_random_bytes is + provided by the selected kernel crypto API RNG. endif # LRNG_DRNG_SWITCH =20 endif # LRNG diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile index 6ebd252db12f..97d2b13d3227 100644 =2D-- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) +=3D lrng_proc.o obj-$(CONFIG_LRNG_DRNG_SWITCH) +=3D lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) +=3D lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) +=3D lrng_drbg.o +obj-$(CONFIG_LRNG_KCAPI) +=3D lrng_kcapi.o diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c new file mode 100644 index 000000000000..caecb3841f5b =2D-- /dev/null +++ b/drivers/char/lrng/lrng_kcapi.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * Backend for the LRNG providing the cryptographic primitives using the + * kernel crypto API. + * + * Copyright (C) 2018 - 2021, Stephan Mueller + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#include "lrng_kcapi_hash.h" + +static char *drng_name =3D NULL; +module_param(drng_name, charp, 0444); +MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG"); + +static char *pool_hash =3D "sha512"; +module_param(pool_hash, charp, 0444); +MODULE_PARM_DESC(pool_hash, + "Kernel crypto API name of hash or keyed message digest to read the ent= ropy pool"); + +static char *seed_hash =3D NULL; +module_param(seed_hash, charp, 0444); +MODULE_PARM_DESC(seed_hash, + "Kernel crypto API name of hash with output size equal to seedsize of D= RNG to bring seed string to the size required by the DRNG"); + +struct lrng_drng_info { + struct crypto_rng *kcapi_rng; + void *lrng_hash; +}; + +static void *lrng_kcapi_drng_hash_alloc(void) +{ + return lrng_kcapi_hash_alloc(pool_hash); +} + +static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf, + u32 inbuflen) +{ + SHASH_DESC_ON_STACK(shash, NULL); + struct lrng_drng_info *lrng_drng_info =3D (struct lrng_drng_info *)drng; + struct crypto_rng *kcapi_rng =3D lrng_drng_info->kcapi_rng; + void *hash =3D lrng_drng_info->lrng_hash; + u32 digestsize =3D lrng_kcapi_hash_digestsize(hash); + u8 digest[64] __aligned(8); + int ret; + + if (!hash) + return crypto_rng_reset(kcapi_rng, inbuf, inbuflen); + + BUG_ON(digestsize > sizeof(digest)); + + ret =3D lrng_kcapi_hash_init(shash, hash) ?: + lrng_kcapi_hash_update(shash, inbuf, inbuflen) ?: + lrng_kcapi_hash_final(shash, digest); + if (ret) + return ret; + + ret =3D crypto_rng_reset(kcapi_rng, digest, digestsize); + if (ret) + return ret; + + memzero_explicit(digest, digestsize); + return 0; +} + +static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf, + u32 outbuflen) +{ + struct lrng_drng_info *lrng_drng_info =3D (struct lrng_drng_info *)drng; + struct crypto_rng *kcapi_rng =3D lrng_drng_info->kcapi_rng; + int ret =3D crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen); + + if (ret < 0) + return ret; + + return outbuflen; +} + +static void *lrng_kcapi_drng_alloc(u32 sec_strength) +{ + struct lrng_drng_info *lrng_drng_info; + struct crypto_rng *kcapi_rng; + int seedsize; + void *ret =3D ERR_PTR(-ENOMEM); + + if (!drng_name) { + pr_err("DRNG name missing\n"); + return ERR_PTR(-EINVAL); + } + + if (!memcmp(drng_name, "drbg", 4) || + !memcmp(drng_name, "stdrng", 6) || + !memcmp(drng_name, "jitterentropy_rng", 17)) { + pr_err("Refusing to load the requested random number generator\n"); + return ERR_PTR(-EINVAL); + } + + lrng_drng_info =3D kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL); + if (!lrng_drng_info) + return ERR_PTR(-ENOMEM); + + kcapi_rng =3D crypto_alloc_rng(drng_name, 0, 0); + if (IS_ERR(kcapi_rng)) { + pr_err("DRNG %s cannot be allocated\n", drng_name); + ret =3D ERR_CAST(kcapi_rng); + goto free; + } + lrng_drng_info->kcapi_rng =3D kcapi_rng; + + seedsize =3D crypto_rng_seedsize(kcapi_rng); + + if (sec_strength > seedsize) + pr_info("Seedsize DRNG (%u bits) lower than security strength of LRNG no= ise source (%u bits)\n", + crypto_rng_seedsize(kcapi_rng) * 8, sec_strength * 8); + + if (seedsize) { + void *lrng_hash; + + if (!seed_hash) { + switch (seedsize) { + case 32: + seed_hash =3D "sha256"; + break; + case 48: + seed_hash =3D "sha384"; + break; + case 64: + seed_hash =3D "sha512"; + break; + default: + pr_err("Seed size %d cannot be processed\n", + seedsize); + goto dealloc; + } + } + + lrng_hash =3D lrng_kcapi_hash_alloc(seed_hash); + if (IS_ERR(lrng_hash)) { + ret =3D ERR_CAST(lrng_hash); + goto dealloc; + } + + if (seedsize !=3D lrng_kcapi_hash_digestsize(lrng_hash)) { + pr_err("Seed hash output size not equal to DRNG seed size\n"); + lrng_kcapi_hash_dealloc(lrng_hash); + ret =3D ERR_PTR(-EINVAL); + goto dealloc; + } + + lrng_drng_info->lrng_hash =3D lrng_hash; + + pr_info("Seed hash %s allocated\n", seed_hash); + } else { + lrng_drng_info->lrng_hash =3D NULL; + } + + pr_info("Kernel crypto API DRNG %s allocated\n", drng_name); + + return lrng_drng_info; + +dealloc: + crypto_free_rng(kcapi_rng); +free: + kfree(lrng_drng_info); + return ret; +} + +static void lrng_kcapi_drng_dealloc(void *drng) +{ + struct lrng_drng_info *lrng_drng_info =3D (struct lrng_drng_info *)drng; + struct crypto_rng *kcapi_rng =3D lrng_drng_info->kcapi_rng; + + crypto_free_rng(kcapi_rng); + if (lrng_drng_info->lrng_hash) + lrng_kcapi_hash_dealloc(lrng_drng_info->lrng_hash); + kfree(lrng_drng_info); + pr_info("DRNG %s deallocated\n", drng_name); +} + +static const char *lrng_kcapi_drng_name(void) +{ + return drng_name; +} + +static const char *lrng_kcapi_pool_hash(void) +{ + return pool_hash; +} + +static const struct lrng_crypto_cb lrng_kcapi_crypto_cb =3D { + .lrng_drng_name =3D lrng_kcapi_drng_name, + .lrng_hash_name =3D lrng_kcapi_pool_hash, + .lrng_drng_alloc =3D lrng_kcapi_drng_alloc, + .lrng_drng_dealloc =3D lrng_kcapi_drng_dealloc, + .lrng_drng_seed_helper =3D lrng_kcapi_drng_seed_helper, + .lrng_drng_generate_helper =3D lrng_kcapi_drng_generate_helper, + .lrng_hash_alloc =3D lrng_kcapi_drng_hash_alloc, + .lrng_hash_dealloc =3D lrng_kcapi_hash_dealloc, + .lrng_hash_digestsize =3D lrng_kcapi_hash_digestsize, + .lrng_hash_init =3D lrng_kcapi_hash_init, + .lrng_hash_update =3D lrng_kcapi_hash_update, + .lrng_hash_final =3D lrng_kcapi_hash_final, +}; + +static int __init lrng_kcapi_init(void) +{ + return lrng_set_drng_cb(&lrng_kcapi_crypto_cb); +} +static void __exit lrng_kcapi_exit(void) +{ + lrng_set_drng_cb(NULL); +} + +late_initcall(lrng_kcapi_init); +module_exit(lrng_kcapi_exit); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG= backend"); =2D-=20 2.29.2