162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * DRBG: Deterministic Random Bits Generator
362306a36Sopenharmony_ci *       Based on NIST Recommended DRBG from NIST SP800-90A with the following
462306a36Sopenharmony_ci *       properties:
562306a36Sopenharmony_ci *		* CTR DRBG with DF with AES-128, AES-192, AES-256 cores
662306a36Sopenharmony_ci *		* Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
762306a36Sopenharmony_ci *		* HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
862306a36Sopenharmony_ci *		* with and without prediction resistance
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Copyright Stephan Mueller <smueller@chronox.de>, 2014
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1362306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1462306a36Sopenharmony_ci * are met:
1562306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1662306a36Sopenharmony_ci *    notice, and the entire permission notice in its entirety,
1762306a36Sopenharmony_ci *    including the disclaimer of warranties.
1862306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
1962306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
2062306a36Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
2162306a36Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote
2262306a36Sopenharmony_ci *    products derived from this software without specific prior
2362306a36Sopenharmony_ci *    written permission.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of
2662306a36Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL are
2762306a36Sopenharmony_ci * required INSTEAD OF the above restrictions.  (This clause is
2862306a36Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and
2962306a36Sopenharmony_ci * the restrictions contained in a BSD-style copyright.)
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3262306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3362306a36Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
3462306a36Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
3562306a36Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3662306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
3762306a36Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3862306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3962306a36Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4062306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4162306a36Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
4262306a36Sopenharmony_ci * DAMAGE.
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci * DRBG Usage
4562306a36Sopenharmony_ci * ==========
4662306a36Sopenharmony_ci * The SP 800-90A DRBG allows the user to specify a personalization string
4762306a36Sopenharmony_ci * for initialization as well as an additional information string for each
4862306a36Sopenharmony_ci * random number request. The following code fragments show how a caller
4962306a36Sopenharmony_ci * uses the kernel crypto API to use the full functionality of the DRBG.
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci * Usage without any additional data
5262306a36Sopenharmony_ci * ---------------------------------
5362306a36Sopenharmony_ci * struct crypto_rng *drng;
5462306a36Sopenharmony_ci * int err;
5562306a36Sopenharmony_ci * char data[DATALEN];
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
5862306a36Sopenharmony_ci * err = crypto_rng_get_bytes(drng, &data, DATALEN);
5962306a36Sopenharmony_ci * crypto_free_rng(drng);
6062306a36Sopenharmony_ci *
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Usage with personalization string during initialization
6362306a36Sopenharmony_ci * -------------------------------------------------------
6462306a36Sopenharmony_ci * struct crypto_rng *drng;
6562306a36Sopenharmony_ci * int err;
6662306a36Sopenharmony_ci * char data[DATALEN];
6762306a36Sopenharmony_ci * struct drbg_string pers;
6862306a36Sopenharmony_ci * char personalization[11] = "some-string";
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * drbg_string_fill(&pers, personalization, strlen(personalization));
7162306a36Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
7262306a36Sopenharmony_ci * // The reset completely re-initializes the DRBG with the provided
7362306a36Sopenharmony_ci * // personalization string
7462306a36Sopenharmony_ci * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
7562306a36Sopenharmony_ci * err = crypto_rng_get_bytes(drng, &data, DATALEN);
7662306a36Sopenharmony_ci * crypto_free_rng(drng);
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * Usage with additional information string during random number request
8062306a36Sopenharmony_ci * ---------------------------------------------------------------------
8162306a36Sopenharmony_ci * struct crypto_rng *drng;
8262306a36Sopenharmony_ci * int err;
8362306a36Sopenharmony_ci * char data[DATALEN];
8462306a36Sopenharmony_ci * char addtl_string[11] = "some-string";
8562306a36Sopenharmony_ci * string drbg_string addtl;
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
8862306a36Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
8962306a36Sopenharmony_ci * // The following call is a wrapper to crypto_rng_get_bytes() and returns
9062306a36Sopenharmony_ci * // the same error codes.
9162306a36Sopenharmony_ci * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
9262306a36Sopenharmony_ci * crypto_free_rng(drng);
9362306a36Sopenharmony_ci *
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci * Usage with personalization and additional information strings
9662306a36Sopenharmony_ci * -------------------------------------------------------------
9762306a36Sopenharmony_ci * Just mix both scenarios above.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#include <crypto/drbg.h>
10162306a36Sopenharmony_ci#include <crypto/internal/cipher.h>
10262306a36Sopenharmony_ci#include <linux/kernel.h>
10362306a36Sopenharmony_ci#include <linux/jiffies.h>
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/***************************************************************
10662306a36Sopenharmony_ci * Backend cipher definitions available to DRBG
10762306a36Sopenharmony_ci ***************************************************************/
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * The order of the DRBG definitions here matter: every DRBG is registered
11162306a36Sopenharmony_ci * as stdrng. Each DRBG receives an increasing cra_priority values the later
11262306a36Sopenharmony_ci * they are defined in this array (see drbg_fill_array).
11362306a36Sopenharmony_ci *
11462306a36Sopenharmony_ci * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and
11562306a36Sopenharmony_ci * the SHA256 / AES 256 over other ciphers. Thus, the favored
11662306a36Sopenharmony_ci * DRBGs are the latest entries in this array.
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_cistatic const struct drbg_core drbg_cores[] = {
11962306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
12062306a36Sopenharmony_ci	{
12162306a36Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH128,
12262306a36Sopenharmony_ci		.statelen = 32, /* 256 bits as defined in 10.2.1 */
12362306a36Sopenharmony_ci		.blocklen_bytes = 16,
12462306a36Sopenharmony_ci		.cra_name = "ctr_aes128",
12562306a36Sopenharmony_ci		.backend_cra_name = "aes",
12662306a36Sopenharmony_ci	}, {
12762306a36Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH192,
12862306a36Sopenharmony_ci		.statelen = 40, /* 320 bits as defined in 10.2.1 */
12962306a36Sopenharmony_ci		.blocklen_bytes = 16,
13062306a36Sopenharmony_ci		.cra_name = "ctr_aes192",
13162306a36Sopenharmony_ci		.backend_cra_name = "aes",
13262306a36Sopenharmony_ci	}, {
13362306a36Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH256,
13462306a36Sopenharmony_ci		.statelen = 48, /* 384 bits as defined in 10.2.1 */
13562306a36Sopenharmony_ci		.blocklen_bytes = 16,
13662306a36Sopenharmony_ci		.cra_name = "ctr_aes256",
13762306a36Sopenharmony_ci		.backend_cra_name = "aes",
13862306a36Sopenharmony_ci	},
13962306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
14062306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
14162306a36Sopenharmony_ci	{
14262306a36Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH128,
14362306a36Sopenharmony_ci		.statelen = 55, /* 440 bits */
14462306a36Sopenharmony_ci		.blocklen_bytes = 20,
14562306a36Sopenharmony_ci		.cra_name = "sha1",
14662306a36Sopenharmony_ci		.backend_cra_name = "sha1",
14762306a36Sopenharmony_ci	}, {
14862306a36Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
14962306a36Sopenharmony_ci		.statelen = 111, /* 888 bits */
15062306a36Sopenharmony_ci		.blocklen_bytes = 48,
15162306a36Sopenharmony_ci		.cra_name = "sha384",
15262306a36Sopenharmony_ci		.backend_cra_name = "sha384",
15362306a36Sopenharmony_ci	}, {
15462306a36Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
15562306a36Sopenharmony_ci		.statelen = 111, /* 888 bits */
15662306a36Sopenharmony_ci		.blocklen_bytes = 64,
15762306a36Sopenharmony_ci		.cra_name = "sha512",
15862306a36Sopenharmony_ci		.backend_cra_name = "sha512",
15962306a36Sopenharmony_ci	}, {
16062306a36Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
16162306a36Sopenharmony_ci		.statelen = 55, /* 440 bits */
16262306a36Sopenharmony_ci		.blocklen_bytes = 32,
16362306a36Sopenharmony_ci		.cra_name = "sha256",
16462306a36Sopenharmony_ci		.backend_cra_name = "sha256",
16562306a36Sopenharmony_ci	},
16662306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
16762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
16862306a36Sopenharmony_ci	{
16962306a36Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH128,
17062306a36Sopenharmony_ci		.statelen = 20, /* block length of cipher */
17162306a36Sopenharmony_ci		.blocklen_bytes = 20,
17262306a36Sopenharmony_ci		.cra_name = "hmac_sha1",
17362306a36Sopenharmony_ci		.backend_cra_name = "hmac(sha1)",
17462306a36Sopenharmony_ci	}, {
17562306a36Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
17662306a36Sopenharmony_ci		.statelen = 48, /* block length of cipher */
17762306a36Sopenharmony_ci		.blocklen_bytes = 48,
17862306a36Sopenharmony_ci		.cra_name = "hmac_sha384",
17962306a36Sopenharmony_ci		.backend_cra_name = "hmac(sha384)",
18062306a36Sopenharmony_ci	}, {
18162306a36Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
18262306a36Sopenharmony_ci		.statelen = 32, /* block length of cipher */
18362306a36Sopenharmony_ci		.blocklen_bytes = 32,
18462306a36Sopenharmony_ci		.cra_name = "hmac_sha256",
18562306a36Sopenharmony_ci		.backend_cra_name = "hmac(sha256)",
18662306a36Sopenharmony_ci	}, {
18762306a36Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
18862306a36Sopenharmony_ci		.statelen = 64, /* block length of cipher */
18962306a36Sopenharmony_ci		.blocklen_bytes = 64,
19062306a36Sopenharmony_ci		.cra_name = "hmac_sha512",
19162306a36Sopenharmony_ci		.backend_cra_name = "hmac(sha512)",
19262306a36Sopenharmony_ci	},
19362306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic int drbg_uninstantiate(struct drbg_state *drbg);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci/******************************************************************
19962306a36Sopenharmony_ci * Generic helper functions
20062306a36Sopenharmony_ci ******************************************************************/
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/*
20362306a36Sopenharmony_ci * Return strength of DRBG according to SP800-90A section 8.4
20462306a36Sopenharmony_ci *
20562306a36Sopenharmony_ci * @flags DRBG flags reference
20662306a36Sopenharmony_ci *
20762306a36Sopenharmony_ci * Return: normalized strength in *bytes* value or 32 as default
20862306a36Sopenharmony_ci *	   to counter programming errors
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic inline unsigned short drbg_sec_strength(drbg_flag_t flags)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	switch (flags & DRBG_STRENGTH_MASK) {
21362306a36Sopenharmony_ci	case DRBG_STRENGTH128:
21462306a36Sopenharmony_ci		return 16;
21562306a36Sopenharmony_ci	case DRBG_STRENGTH192:
21662306a36Sopenharmony_ci		return 24;
21762306a36Sopenharmony_ci	case DRBG_STRENGTH256:
21862306a36Sopenharmony_ci		return 32;
21962306a36Sopenharmony_ci	default:
22062306a36Sopenharmony_ci		return 32;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/*
22562306a36Sopenharmony_ci * FIPS 140-2 continuous self test for the noise source
22662306a36Sopenharmony_ci * The test is performed on the noise source input data. Thus, the function
22762306a36Sopenharmony_ci * implicitly knows the size of the buffer to be equal to the security
22862306a36Sopenharmony_ci * strength.
22962306a36Sopenharmony_ci *
23062306a36Sopenharmony_ci * Note, this function disregards the nonce trailing the entropy data during
23162306a36Sopenharmony_ci * initial seeding.
23262306a36Sopenharmony_ci *
23362306a36Sopenharmony_ci * drbg->drbg_mutex must have been taken.
23462306a36Sopenharmony_ci *
23562306a36Sopenharmony_ci * @drbg DRBG handle
23662306a36Sopenharmony_ci * @entropy buffer of seed data to be checked
23762306a36Sopenharmony_ci *
23862306a36Sopenharmony_ci * return:
23962306a36Sopenharmony_ci *	0 on success
24062306a36Sopenharmony_ci *	-EAGAIN on when the CTRNG is not yet primed
24162306a36Sopenharmony_ci *	< 0 on error
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_cistatic int drbg_fips_continuous_test(struct drbg_state *drbg,
24462306a36Sopenharmony_ci				     const unsigned char *entropy)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
24762306a36Sopenharmony_ci	int ret = 0;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	if (!IS_ENABLED(CONFIG_CRYPTO_FIPS))
25062306a36Sopenharmony_ci		return 0;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	/* skip test if we test the overall system */
25362306a36Sopenharmony_ci	if (list_empty(&drbg->test_data.list))
25462306a36Sopenharmony_ci		return 0;
25562306a36Sopenharmony_ci	/* only perform test in FIPS mode */
25662306a36Sopenharmony_ci	if (!fips_enabled)
25762306a36Sopenharmony_ci		return 0;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	if (!drbg->fips_primed) {
26062306a36Sopenharmony_ci		/* Priming of FIPS test */
26162306a36Sopenharmony_ci		memcpy(drbg->prev, entropy, entropylen);
26262306a36Sopenharmony_ci		drbg->fips_primed = true;
26362306a36Sopenharmony_ci		/* priming: another round is needed */
26462306a36Sopenharmony_ci		return -EAGAIN;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci	ret = memcmp(drbg->prev, entropy, entropylen);
26762306a36Sopenharmony_ci	if (!ret)
26862306a36Sopenharmony_ci		panic("DRBG continuous self test failed\n");
26962306a36Sopenharmony_ci	memcpy(drbg->prev, entropy, entropylen);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	/* the test shall pass when the two values are not equal */
27262306a36Sopenharmony_ci	return 0;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/*
27662306a36Sopenharmony_ci * Convert an integer into a byte representation of this integer.
27762306a36Sopenharmony_ci * The byte representation is big-endian
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci * @val value to be converted
28062306a36Sopenharmony_ci * @buf buffer holding the converted integer -- caller must ensure that
28162306a36Sopenharmony_ci *      buffer size is at least 32 bit
28262306a36Sopenharmony_ci */
28362306a36Sopenharmony_ci#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
28462306a36Sopenharmony_cistatic inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	struct s {
28762306a36Sopenharmony_ci		__be32 conv;
28862306a36Sopenharmony_ci	};
28962306a36Sopenharmony_ci	struct s *conversion = (struct s *) buf;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	conversion->conv = cpu_to_be32(val);
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/******************************************************************
29662306a36Sopenharmony_ci * CTR DRBG callback functions
29762306a36Sopenharmony_ci ******************************************************************/
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
30062306a36Sopenharmony_ci#define CRYPTO_DRBG_CTR_STRING "CTR "
30162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes256");
30262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes256");
30362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes192");
30462306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes192");
30562306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128");
30662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128");
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic void drbg_kcapi_symsetkey(struct drbg_state *drbg,
30962306a36Sopenharmony_ci				 const unsigned char *key);
31062306a36Sopenharmony_cistatic int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
31162306a36Sopenharmony_ci			  const struct drbg_string *in);
31262306a36Sopenharmony_cistatic int drbg_init_sym_kernel(struct drbg_state *drbg);
31362306a36Sopenharmony_cistatic int drbg_fini_sym_kernel(struct drbg_state *drbg);
31462306a36Sopenharmony_cistatic int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
31562306a36Sopenharmony_ci			      u8 *inbuf, u32 inbuflen,
31662306a36Sopenharmony_ci			      u8 *outbuf, u32 outlen);
31762306a36Sopenharmony_ci#define DRBG_OUTSCRATCHLEN 256
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci/* BCC function for CTR DRBG as defined in 10.4.3 */
32062306a36Sopenharmony_cistatic int drbg_ctr_bcc(struct drbg_state *drbg,
32162306a36Sopenharmony_ci			unsigned char *out, const unsigned char *key,
32262306a36Sopenharmony_ci			struct list_head *in)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	int ret = 0;
32562306a36Sopenharmony_ci	struct drbg_string *curr = NULL;
32662306a36Sopenharmony_ci	struct drbg_string data;
32762306a36Sopenharmony_ci	short cnt = 0;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	drbg_string_fill(&data, out, drbg_blocklen(drbg));
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* 10.4.3 step 2 / 4 */
33262306a36Sopenharmony_ci	drbg_kcapi_symsetkey(drbg, key);
33362306a36Sopenharmony_ci	list_for_each_entry(curr, in, list) {
33462306a36Sopenharmony_ci		const unsigned char *pos = curr->buf;
33562306a36Sopenharmony_ci		size_t len = curr->len;
33662306a36Sopenharmony_ci		/* 10.4.3 step 4.1 */
33762306a36Sopenharmony_ci		while (len) {
33862306a36Sopenharmony_ci			/* 10.4.3 step 4.2 */
33962306a36Sopenharmony_ci			if (drbg_blocklen(drbg) == cnt) {
34062306a36Sopenharmony_ci				cnt = 0;
34162306a36Sopenharmony_ci				ret = drbg_kcapi_sym(drbg, out, &data);
34262306a36Sopenharmony_ci				if (ret)
34362306a36Sopenharmony_ci					return ret;
34462306a36Sopenharmony_ci			}
34562306a36Sopenharmony_ci			out[cnt] ^= *pos;
34662306a36Sopenharmony_ci			pos++;
34762306a36Sopenharmony_ci			cnt++;
34862306a36Sopenharmony_ci			len--;
34962306a36Sopenharmony_ci		}
35062306a36Sopenharmony_ci	}
35162306a36Sopenharmony_ci	/* 10.4.3 step 4.2 for last block */
35262306a36Sopenharmony_ci	if (cnt)
35362306a36Sopenharmony_ci		ret = drbg_kcapi_sym(drbg, out, &data);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	return ret;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci/*
35962306a36Sopenharmony_ci * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
36062306a36Sopenharmony_ci * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
36162306a36Sopenharmony_ci * the scratchpad is used as follows:
36262306a36Sopenharmony_ci * drbg_ctr_update:
36362306a36Sopenharmony_ci *	temp
36462306a36Sopenharmony_ci *		start: drbg->scratchpad
36562306a36Sopenharmony_ci *		length: drbg_statelen(drbg) + drbg_blocklen(drbg)
36662306a36Sopenharmony_ci *			note: the cipher writing into this variable works
36762306a36Sopenharmony_ci *			blocklen-wise. Now, when the statelen is not a multiple
36862306a36Sopenharmony_ci *			of blocklen, the generateion loop below "spills over"
36962306a36Sopenharmony_ci *			by at most blocklen. Thus, we need to give sufficient
37062306a36Sopenharmony_ci *			memory.
37162306a36Sopenharmony_ci *	df_data
37262306a36Sopenharmony_ci *		start: drbg->scratchpad +
37362306a36Sopenharmony_ci *				drbg_statelen(drbg) + drbg_blocklen(drbg)
37462306a36Sopenharmony_ci *		length: drbg_statelen(drbg)
37562306a36Sopenharmony_ci *
37662306a36Sopenharmony_ci * drbg_ctr_df:
37762306a36Sopenharmony_ci *	pad
37862306a36Sopenharmony_ci *		start: df_data + drbg_statelen(drbg)
37962306a36Sopenharmony_ci *		length: drbg_blocklen(drbg)
38062306a36Sopenharmony_ci *	iv
38162306a36Sopenharmony_ci *		start: pad + drbg_blocklen(drbg)
38262306a36Sopenharmony_ci *		length: drbg_blocklen(drbg)
38362306a36Sopenharmony_ci *	temp
38462306a36Sopenharmony_ci *		start: iv + drbg_blocklen(drbg)
38562306a36Sopenharmony_ci *		length: drbg_satelen(drbg) + drbg_blocklen(drbg)
38662306a36Sopenharmony_ci *			note: temp is the buffer that the BCC function operates
38762306a36Sopenharmony_ci *			on. BCC operates blockwise. drbg_statelen(drbg)
38862306a36Sopenharmony_ci *			is sufficient when the DRBG state length is a multiple
38962306a36Sopenharmony_ci *			of the block size. For AES192 (and maybe other ciphers)
39062306a36Sopenharmony_ci *			this is not correct and the length for temp is
39162306a36Sopenharmony_ci *			insufficient (yes, that also means for such ciphers,
39262306a36Sopenharmony_ci *			the final output of all BCC rounds are truncated).
39362306a36Sopenharmony_ci *			Therefore, add drbg_blocklen(drbg) to cover all
39462306a36Sopenharmony_ci *			possibilities.
39562306a36Sopenharmony_ci */
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/* Derivation Function for CTR DRBG as defined in 10.4.2 */
39862306a36Sopenharmony_cistatic int drbg_ctr_df(struct drbg_state *drbg,
39962306a36Sopenharmony_ci		       unsigned char *df_data, size_t bytes_to_return,
40062306a36Sopenharmony_ci		       struct list_head *seedlist)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	int ret = -EFAULT;
40362306a36Sopenharmony_ci	unsigned char L_N[8];
40462306a36Sopenharmony_ci	/* S3 is input */
40562306a36Sopenharmony_ci	struct drbg_string S1, S2, S4, cipherin;
40662306a36Sopenharmony_ci	LIST_HEAD(bcc_list);
40762306a36Sopenharmony_ci	unsigned char *pad = df_data + drbg_statelen(drbg);
40862306a36Sopenharmony_ci	unsigned char *iv = pad + drbg_blocklen(drbg);
40962306a36Sopenharmony_ci	unsigned char *temp = iv + drbg_blocklen(drbg);
41062306a36Sopenharmony_ci	size_t padlen = 0;
41162306a36Sopenharmony_ci	unsigned int templen = 0;
41262306a36Sopenharmony_ci	/* 10.4.2 step 7 */
41362306a36Sopenharmony_ci	unsigned int i = 0;
41462306a36Sopenharmony_ci	/* 10.4.2 step 8 */
41562306a36Sopenharmony_ci	const unsigned char *K = (unsigned char *)
41662306a36Sopenharmony_ci			   "\x00\x01\x02\x03\x04\x05\x06\x07"
41762306a36Sopenharmony_ci			   "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
41862306a36Sopenharmony_ci			   "\x10\x11\x12\x13\x14\x15\x16\x17"
41962306a36Sopenharmony_ci			   "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
42062306a36Sopenharmony_ci	unsigned char *X;
42162306a36Sopenharmony_ci	size_t generated_len = 0;
42262306a36Sopenharmony_ci	size_t inputlen = 0;
42362306a36Sopenharmony_ci	struct drbg_string *seed = NULL;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	memset(pad, 0, drbg_blocklen(drbg));
42662306a36Sopenharmony_ci	memset(iv, 0, drbg_blocklen(drbg));
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	/* 10.4.2 step 1 is implicit as we work byte-wise */
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	/* 10.4.2 step 2 */
43162306a36Sopenharmony_ci	if ((512/8) < bytes_to_return)
43262306a36Sopenharmony_ci		return -EINVAL;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	/* 10.4.2 step 2 -- calculate the entire length of all input data */
43562306a36Sopenharmony_ci	list_for_each_entry(seed, seedlist, list)
43662306a36Sopenharmony_ci		inputlen += seed->len;
43762306a36Sopenharmony_ci	drbg_cpu_to_be32(inputlen, &L_N[0]);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	/* 10.4.2 step 3 */
44062306a36Sopenharmony_ci	drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
44362306a36Sopenharmony_ci	padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
44462306a36Sopenharmony_ci	/* wrap the padlen appropriately */
44562306a36Sopenharmony_ci	if (padlen)
44662306a36Sopenharmony_ci		padlen = drbg_blocklen(drbg) - padlen;
44762306a36Sopenharmony_ci	/*
44862306a36Sopenharmony_ci	 * pad / padlen contains the 0x80 byte and the following zero bytes.
44962306a36Sopenharmony_ci	 * As the calculated padlen value only covers the number of zero
45062306a36Sopenharmony_ci	 * bytes, this value has to be incremented by one for the 0x80 byte.
45162306a36Sopenharmony_ci	 */
45262306a36Sopenharmony_ci	padlen++;
45362306a36Sopenharmony_ci	pad[0] = 0x80;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* 10.4.2 step 4 -- first fill the linked list and then order it */
45662306a36Sopenharmony_ci	drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
45762306a36Sopenharmony_ci	list_add_tail(&S1.list, &bcc_list);
45862306a36Sopenharmony_ci	drbg_string_fill(&S2, L_N, sizeof(L_N));
45962306a36Sopenharmony_ci	list_add_tail(&S2.list, &bcc_list);
46062306a36Sopenharmony_ci	list_splice_tail(seedlist, &bcc_list);
46162306a36Sopenharmony_ci	drbg_string_fill(&S4, pad, padlen);
46262306a36Sopenharmony_ci	list_add_tail(&S4.list, &bcc_list);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/* 10.4.2 step 9 */
46562306a36Sopenharmony_ci	while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
46662306a36Sopenharmony_ci		/*
46762306a36Sopenharmony_ci		 * 10.4.2 step 9.1 - the padding is implicit as the buffer
46862306a36Sopenharmony_ci		 * holds zeros after allocation -- even the increment of i
46962306a36Sopenharmony_ci		 * is irrelevant as the increment remains within length of i
47062306a36Sopenharmony_ci		 */
47162306a36Sopenharmony_ci		drbg_cpu_to_be32(i, iv);
47262306a36Sopenharmony_ci		/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
47362306a36Sopenharmony_ci		ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
47462306a36Sopenharmony_ci		if (ret)
47562306a36Sopenharmony_ci			goto out;
47662306a36Sopenharmony_ci		/* 10.4.2 step 9.3 */
47762306a36Sopenharmony_ci		i++;
47862306a36Sopenharmony_ci		templen += drbg_blocklen(drbg);
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* 10.4.2 step 11 */
48262306a36Sopenharmony_ci	X = temp + (drbg_keylen(drbg));
48362306a36Sopenharmony_ci	drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	/* 10.4.2 step 12: overwriting of outval is implemented in next step */
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	/* 10.4.2 step 13 */
48862306a36Sopenharmony_ci	drbg_kcapi_symsetkey(drbg, temp);
48962306a36Sopenharmony_ci	while (generated_len < bytes_to_return) {
49062306a36Sopenharmony_ci		short blocklen = 0;
49162306a36Sopenharmony_ci		/*
49262306a36Sopenharmony_ci		 * 10.4.2 step 13.1: the truncation of the key length is
49362306a36Sopenharmony_ci		 * implicit as the key is only drbg_blocklen in size based on
49462306a36Sopenharmony_ci		 * the implementation of the cipher function callback
49562306a36Sopenharmony_ci		 */
49662306a36Sopenharmony_ci		ret = drbg_kcapi_sym(drbg, X, &cipherin);
49762306a36Sopenharmony_ci		if (ret)
49862306a36Sopenharmony_ci			goto out;
49962306a36Sopenharmony_ci		blocklen = (drbg_blocklen(drbg) <
50062306a36Sopenharmony_ci				(bytes_to_return - generated_len)) ?
50162306a36Sopenharmony_ci			    drbg_blocklen(drbg) :
50262306a36Sopenharmony_ci				(bytes_to_return - generated_len);
50362306a36Sopenharmony_ci		/* 10.4.2 step 13.2 and 14 */
50462306a36Sopenharmony_ci		memcpy(df_data + generated_len, X, blocklen);
50562306a36Sopenharmony_ci		generated_len += blocklen;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	ret = 0;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ciout:
51162306a36Sopenharmony_ci	memset(iv, 0, drbg_blocklen(drbg));
51262306a36Sopenharmony_ci	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
51362306a36Sopenharmony_ci	memset(pad, 0, drbg_blocklen(drbg));
51462306a36Sopenharmony_ci	return ret;
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci/*
51862306a36Sopenharmony_ci * update function of CTR DRBG as defined in 10.2.1.2
51962306a36Sopenharmony_ci *
52062306a36Sopenharmony_ci * The reseed variable has an enhanced meaning compared to the update
52162306a36Sopenharmony_ci * functions of the other DRBGs as follows:
52262306a36Sopenharmony_ci * 0 => initial seed from initialization
52362306a36Sopenharmony_ci * 1 => reseed via drbg_seed
52462306a36Sopenharmony_ci * 2 => first invocation from drbg_ctr_update when addtl is present. In
52562306a36Sopenharmony_ci *      this case, the df_data scratchpad is not deleted so that it is
52662306a36Sopenharmony_ci *      available for another calls to prevent calling the DF function
52762306a36Sopenharmony_ci *      again.
52862306a36Sopenharmony_ci * 3 => second invocation from drbg_ctr_update. When the update function
52962306a36Sopenharmony_ci *      was called with addtl, the df_data memory already contains the
53062306a36Sopenharmony_ci *      DFed addtl information and we do not need to call DF again.
53162306a36Sopenharmony_ci */
53262306a36Sopenharmony_cistatic int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
53362306a36Sopenharmony_ci			   int reseed)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	int ret = -EFAULT;
53662306a36Sopenharmony_ci	/* 10.2.1.2 step 1 */
53762306a36Sopenharmony_ci	unsigned char *temp = drbg->scratchpad;
53862306a36Sopenharmony_ci	unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
53962306a36Sopenharmony_ci				 drbg_blocklen(drbg);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	if (3 > reseed)
54262306a36Sopenharmony_ci		memset(df_data, 0, drbg_statelen(drbg));
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	if (!reseed) {
54562306a36Sopenharmony_ci		/*
54662306a36Sopenharmony_ci		 * The DRBG uses the CTR mode of the underlying AES cipher. The
54762306a36Sopenharmony_ci		 * CTR mode increments the counter value after the AES operation
54862306a36Sopenharmony_ci		 * but SP800-90A requires that the counter is incremented before
54962306a36Sopenharmony_ci		 * the AES operation. Hence, we increment it at the time we set
55062306a36Sopenharmony_ci		 * it by one.
55162306a36Sopenharmony_ci		 */
55262306a36Sopenharmony_ci		crypto_inc(drbg->V, drbg_blocklen(drbg));
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci		ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
55562306a36Sopenharmony_ci					     drbg_keylen(drbg));
55662306a36Sopenharmony_ci		if (ret)
55762306a36Sopenharmony_ci			goto out;
55862306a36Sopenharmony_ci	}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	/* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
56162306a36Sopenharmony_ci	if (seed) {
56262306a36Sopenharmony_ci		ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
56362306a36Sopenharmony_ci		if (ret)
56462306a36Sopenharmony_ci			goto out;
56562306a36Sopenharmony_ci	}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg),
56862306a36Sopenharmony_ci				 temp, drbg_statelen(drbg));
56962306a36Sopenharmony_ci	if (ret)
57062306a36Sopenharmony_ci		return ret;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	/* 10.2.1.2 step 5 */
57362306a36Sopenharmony_ci	ret = crypto_skcipher_setkey(drbg->ctr_handle, temp,
57462306a36Sopenharmony_ci				     drbg_keylen(drbg));
57562306a36Sopenharmony_ci	if (ret)
57662306a36Sopenharmony_ci		goto out;
57762306a36Sopenharmony_ci	/* 10.2.1.2 step 6 */
57862306a36Sopenharmony_ci	memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
57962306a36Sopenharmony_ci	/* See above: increment counter by one to compensate timing of CTR op */
58062306a36Sopenharmony_ci	crypto_inc(drbg->V, drbg_blocklen(drbg));
58162306a36Sopenharmony_ci	ret = 0;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ciout:
58462306a36Sopenharmony_ci	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
58562306a36Sopenharmony_ci	if (2 != reseed)
58662306a36Sopenharmony_ci		memset(df_data, 0, drbg_statelen(drbg));
58762306a36Sopenharmony_ci	return ret;
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci/*
59162306a36Sopenharmony_ci * scratchpad use: drbg_ctr_update is called independently from
59262306a36Sopenharmony_ci * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
59362306a36Sopenharmony_ci */
59462306a36Sopenharmony_ci/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
59562306a36Sopenharmony_cistatic int drbg_ctr_generate(struct drbg_state *drbg,
59662306a36Sopenharmony_ci			     unsigned char *buf, unsigned int buflen,
59762306a36Sopenharmony_ci			     struct list_head *addtl)
59862306a36Sopenharmony_ci{
59962306a36Sopenharmony_ci	int ret;
60062306a36Sopenharmony_ci	int len = min_t(int, buflen, INT_MAX);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	/* 10.2.1.5.2 step 2 */
60362306a36Sopenharmony_ci	if (addtl && !list_empty(addtl)) {
60462306a36Sopenharmony_ci		ret = drbg_ctr_update(drbg, addtl, 2);
60562306a36Sopenharmony_ci		if (ret)
60662306a36Sopenharmony_ci			return 0;
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	/* 10.2.1.5.2 step 4.1 */
61062306a36Sopenharmony_ci	ret = drbg_kcapi_sym_ctr(drbg, NULL, 0, buf, len);
61162306a36Sopenharmony_ci	if (ret)
61262306a36Sopenharmony_ci		return ret;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	/* 10.2.1.5.2 step 6 */
61562306a36Sopenharmony_ci	ret = drbg_ctr_update(drbg, NULL, 3);
61662306a36Sopenharmony_ci	if (ret)
61762306a36Sopenharmony_ci		len = ret;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return len;
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic const struct drbg_state_ops drbg_ctr_ops = {
62362306a36Sopenharmony_ci	.update		= drbg_ctr_update,
62462306a36Sopenharmony_ci	.generate	= drbg_ctr_generate,
62562306a36Sopenharmony_ci	.crypto_init	= drbg_init_sym_kernel,
62662306a36Sopenharmony_ci	.crypto_fini	= drbg_fini_sym_kernel,
62762306a36Sopenharmony_ci};
62862306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci/******************************************************************
63162306a36Sopenharmony_ci * HMAC DRBG callback functions
63262306a36Sopenharmony_ci ******************************************************************/
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
63562306a36Sopenharmony_cistatic int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
63662306a36Sopenharmony_ci			   const struct list_head *in);
63762306a36Sopenharmony_cistatic void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
63862306a36Sopenharmony_ci				  const unsigned char *key);
63962306a36Sopenharmony_cistatic int drbg_init_hash_kernel(struct drbg_state *drbg);
64062306a36Sopenharmony_cistatic int drbg_fini_hash_kernel(struct drbg_state *drbg);
64162306a36Sopenharmony_ci#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
64462306a36Sopenharmony_ci#define CRYPTO_DRBG_HMAC_STRING "HMAC "
64562306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
64662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
64762306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384");
64862306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha384");
64962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha256");
65062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha256");
65162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha1");
65262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha1");
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci/* update function of HMAC DRBG as defined in 10.1.2.2 */
65562306a36Sopenharmony_cistatic int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
65662306a36Sopenharmony_ci			    int reseed)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	int ret = -EFAULT;
65962306a36Sopenharmony_ci	int i = 0;
66062306a36Sopenharmony_ci	struct drbg_string seed1, seed2, vdata;
66162306a36Sopenharmony_ci	LIST_HEAD(seedlist);
66262306a36Sopenharmony_ci	LIST_HEAD(vdatalist);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	if (!reseed) {
66562306a36Sopenharmony_ci		/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
66662306a36Sopenharmony_ci		memset(drbg->V, 1, drbg_statelen(drbg));
66762306a36Sopenharmony_ci		drbg_kcapi_hmacsetkey(drbg, drbg->C);
66862306a36Sopenharmony_ci	}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
67162306a36Sopenharmony_ci	list_add_tail(&seed1.list, &seedlist);
67262306a36Sopenharmony_ci	/* buffer of seed2 will be filled in for loop below with one byte */
67362306a36Sopenharmony_ci	drbg_string_fill(&seed2, NULL, 1);
67462306a36Sopenharmony_ci	list_add_tail(&seed2.list, &seedlist);
67562306a36Sopenharmony_ci	/* input data of seed is allowed to be NULL at this point */
67662306a36Sopenharmony_ci	if (seed)
67762306a36Sopenharmony_ci		list_splice_tail(seed, &seedlist);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
68062306a36Sopenharmony_ci	list_add_tail(&vdata.list, &vdatalist);
68162306a36Sopenharmony_ci	for (i = 2; 0 < i; i--) {
68262306a36Sopenharmony_ci		/* first round uses 0x0, second 0x1 */
68362306a36Sopenharmony_ci		unsigned char prefix = DRBG_PREFIX0;
68462306a36Sopenharmony_ci		if (1 == i)
68562306a36Sopenharmony_ci			prefix = DRBG_PREFIX1;
68662306a36Sopenharmony_ci		/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
68762306a36Sopenharmony_ci		seed2.buf = &prefix;
68862306a36Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
68962306a36Sopenharmony_ci		if (ret)
69062306a36Sopenharmony_ci			return ret;
69162306a36Sopenharmony_ci		drbg_kcapi_hmacsetkey(drbg, drbg->C);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		/* 10.1.2.2 step 2 and 5 -- HMAC for V */
69462306a36Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
69562306a36Sopenharmony_ci		if (ret)
69662306a36Sopenharmony_ci			return ret;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci		/* 10.1.2.2 step 3 */
69962306a36Sopenharmony_ci		if (!seed)
70062306a36Sopenharmony_ci			return ret;
70162306a36Sopenharmony_ci	}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	return 0;
70462306a36Sopenharmony_ci}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci/* generate function of HMAC DRBG as defined in 10.1.2.5 */
70762306a36Sopenharmony_cistatic int drbg_hmac_generate(struct drbg_state *drbg,
70862306a36Sopenharmony_ci			      unsigned char *buf,
70962306a36Sopenharmony_ci			      unsigned int buflen,
71062306a36Sopenharmony_ci			      struct list_head *addtl)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	int len = 0;
71362306a36Sopenharmony_ci	int ret = 0;
71462306a36Sopenharmony_ci	struct drbg_string data;
71562306a36Sopenharmony_ci	LIST_HEAD(datalist);
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	/* 10.1.2.5 step 2 */
71862306a36Sopenharmony_ci	if (addtl && !list_empty(addtl)) {
71962306a36Sopenharmony_ci		ret = drbg_hmac_update(drbg, addtl, 1);
72062306a36Sopenharmony_ci		if (ret)
72162306a36Sopenharmony_ci			return ret;
72262306a36Sopenharmony_ci	}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
72562306a36Sopenharmony_ci	list_add_tail(&data.list, &datalist);
72662306a36Sopenharmony_ci	while (len < buflen) {
72762306a36Sopenharmony_ci		unsigned int outlen = 0;
72862306a36Sopenharmony_ci		/* 10.1.2.5 step 4.1 */
72962306a36Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
73062306a36Sopenharmony_ci		if (ret)
73162306a36Sopenharmony_ci			return ret;
73262306a36Sopenharmony_ci		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
73362306a36Sopenharmony_ci			  drbg_blocklen(drbg) : (buflen - len);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci		/* 10.1.2.5 step 4.2 */
73662306a36Sopenharmony_ci		memcpy(buf + len, drbg->V, outlen);
73762306a36Sopenharmony_ci		len += outlen;
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	/* 10.1.2.5 step 6 */
74162306a36Sopenharmony_ci	if (addtl && !list_empty(addtl))
74262306a36Sopenharmony_ci		ret = drbg_hmac_update(drbg, addtl, 1);
74362306a36Sopenharmony_ci	else
74462306a36Sopenharmony_ci		ret = drbg_hmac_update(drbg, NULL, 1);
74562306a36Sopenharmony_ci	if (ret)
74662306a36Sopenharmony_ci		return ret;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	return len;
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic const struct drbg_state_ops drbg_hmac_ops = {
75262306a36Sopenharmony_ci	.update		= drbg_hmac_update,
75362306a36Sopenharmony_ci	.generate	= drbg_hmac_generate,
75462306a36Sopenharmony_ci	.crypto_init	= drbg_init_hash_kernel,
75562306a36Sopenharmony_ci	.crypto_fini	= drbg_fini_hash_kernel,
75662306a36Sopenharmony_ci};
75762306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci/******************************************************************
76062306a36Sopenharmony_ci * Hash DRBG callback functions
76162306a36Sopenharmony_ci ******************************************************************/
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
76462306a36Sopenharmony_ci#define CRYPTO_DRBG_HASH_STRING "HASH "
76562306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha512");
76662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha512");
76762306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha384");
76862306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha384");
76962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha256");
77062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha256");
77162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha1");
77262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha1");
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci/*
77562306a36Sopenharmony_ci * Increment buffer
77662306a36Sopenharmony_ci *
77762306a36Sopenharmony_ci * @dst buffer to increment
77862306a36Sopenharmony_ci * @add value to add
77962306a36Sopenharmony_ci */
78062306a36Sopenharmony_cistatic inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
78162306a36Sopenharmony_ci				const unsigned char *add, size_t addlen)
78262306a36Sopenharmony_ci{
78362306a36Sopenharmony_ci	/* implied: dstlen > addlen */
78462306a36Sopenharmony_ci	unsigned char *dstptr;
78562306a36Sopenharmony_ci	const unsigned char *addptr;
78662306a36Sopenharmony_ci	unsigned int remainder = 0;
78762306a36Sopenharmony_ci	size_t len = addlen;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	dstptr = dst + (dstlen-1);
79062306a36Sopenharmony_ci	addptr = add + (addlen-1);
79162306a36Sopenharmony_ci	while (len) {
79262306a36Sopenharmony_ci		remainder += *dstptr + *addptr;
79362306a36Sopenharmony_ci		*dstptr = remainder & 0xff;
79462306a36Sopenharmony_ci		remainder >>= 8;
79562306a36Sopenharmony_ci		len--; dstptr--; addptr--;
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci	len = dstlen - addlen;
79862306a36Sopenharmony_ci	while (len && remainder > 0) {
79962306a36Sopenharmony_ci		remainder = *dstptr + 1;
80062306a36Sopenharmony_ci		*dstptr = remainder & 0xff;
80162306a36Sopenharmony_ci		remainder >>= 8;
80262306a36Sopenharmony_ci		len--; dstptr--;
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci/*
80762306a36Sopenharmony_ci * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
80862306a36Sopenharmony_ci * interlinked, the scratchpad is used as follows:
80962306a36Sopenharmony_ci * drbg_hash_update
81062306a36Sopenharmony_ci *	start: drbg->scratchpad
81162306a36Sopenharmony_ci *	length: drbg_statelen(drbg)
81262306a36Sopenharmony_ci * drbg_hash_df:
81362306a36Sopenharmony_ci *	start: drbg->scratchpad + drbg_statelen(drbg)
81462306a36Sopenharmony_ci *	length: drbg_blocklen(drbg)
81562306a36Sopenharmony_ci *
81662306a36Sopenharmony_ci * drbg_hash_process_addtl uses the scratchpad, but fully completes
81762306a36Sopenharmony_ci * before either of the functions mentioned before are invoked. Therefore,
81862306a36Sopenharmony_ci * drbg_hash_process_addtl does not need to be specifically considered.
81962306a36Sopenharmony_ci */
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci/* Derivation Function for Hash DRBG as defined in 10.4.1 */
82262306a36Sopenharmony_cistatic int drbg_hash_df(struct drbg_state *drbg,
82362306a36Sopenharmony_ci			unsigned char *outval, size_t outlen,
82462306a36Sopenharmony_ci			struct list_head *entropylist)
82562306a36Sopenharmony_ci{
82662306a36Sopenharmony_ci	int ret = 0;
82762306a36Sopenharmony_ci	size_t len = 0;
82862306a36Sopenharmony_ci	unsigned char input[5];
82962306a36Sopenharmony_ci	unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
83062306a36Sopenharmony_ci	struct drbg_string data;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	/* 10.4.1 step 3 */
83362306a36Sopenharmony_ci	input[0] = 1;
83462306a36Sopenharmony_ci	drbg_cpu_to_be32((outlen * 8), &input[1]);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
83762306a36Sopenharmony_ci	drbg_string_fill(&data, input, 5);
83862306a36Sopenharmony_ci	list_add(&data.list, entropylist);
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/* 10.4.1 step 4 */
84162306a36Sopenharmony_ci	while (len < outlen) {
84262306a36Sopenharmony_ci		short blocklen = 0;
84362306a36Sopenharmony_ci		/* 10.4.1 step 4.1 */
84462306a36Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, tmp, entropylist);
84562306a36Sopenharmony_ci		if (ret)
84662306a36Sopenharmony_ci			goto out;
84762306a36Sopenharmony_ci		/* 10.4.1 step 4.2 */
84862306a36Sopenharmony_ci		input[0]++;
84962306a36Sopenharmony_ci		blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
85062306a36Sopenharmony_ci			    drbg_blocklen(drbg) : (outlen - len);
85162306a36Sopenharmony_ci		memcpy(outval + len, tmp, blocklen);
85262306a36Sopenharmony_ci		len += blocklen;
85362306a36Sopenharmony_ci	}
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ciout:
85662306a36Sopenharmony_ci	memset(tmp, 0, drbg_blocklen(drbg));
85762306a36Sopenharmony_ci	return ret;
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
86162306a36Sopenharmony_cistatic int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
86262306a36Sopenharmony_ci			    int reseed)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	int ret = 0;
86562306a36Sopenharmony_ci	struct drbg_string data1, data2;
86662306a36Sopenharmony_ci	LIST_HEAD(datalist);
86762306a36Sopenharmony_ci	LIST_HEAD(datalist2);
86862306a36Sopenharmony_ci	unsigned char *V = drbg->scratchpad;
86962306a36Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX1;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	if (!seed)
87262306a36Sopenharmony_ci		return -EINVAL;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	if (reseed) {
87562306a36Sopenharmony_ci		/* 10.1.1.3 step 1 */
87662306a36Sopenharmony_ci		memcpy(V, drbg->V, drbg_statelen(drbg));
87762306a36Sopenharmony_ci		drbg_string_fill(&data1, &prefix, 1);
87862306a36Sopenharmony_ci		list_add_tail(&data1.list, &datalist);
87962306a36Sopenharmony_ci		drbg_string_fill(&data2, V, drbg_statelen(drbg));
88062306a36Sopenharmony_ci		list_add_tail(&data2.list, &datalist);
88162306a36Sopenharmony_ci	}
88262306a36Sopenharmony_ci	list_splice_tail(seed, &datalist);
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
88562306a36Sopenharmony_ci	ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
88662306a36Sopenharmony_ci	if (ret)
88762306a36Sopenharmony_ci		goto out;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 4  */
89062306a36Sopenharmony_ci	prefix = DRBG_PREFIX0;
89162306a36Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
89262306a36Sopenharmony_ci	list_add_tail(&data1.list, &datalist2);
89362306a36Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
89462306a36Sopenharmony_ci	list_add_tail(&data2.list, &datalist2);
89562306a36Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 4 */
89662306a36Sopenharmony_ci	ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ciout:
89962306a36Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_statelen(drbg));
90062306a36Sopenharmony_ci	return ret;
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci/* processing of additional information string for Hash DRBG */
90462306a36Sopenharmony_cistatic int drbg_hash_process_addtl(struct drbg_state *drbg,
90562306a36Sopenharmony_ci				   struct list_head *addtl)
90662306a36Sopenharmony_ci{
90762306a36Sopenharmony_ci	int ret = 0;
90862306a36Sopenharmony_ci	struct drbg_string data1, data2;
90962306a36Sopenharmony_ci	LIST_HEAD(datalist);
91062306a36Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX2;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	/* 10.1.1.4 step 2 */
91362306a36Sopenharmony_ci	if (!addtl || list_empty(addtl))
91462306a36Sopenharmony_ci		return 0;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	/* 10.1.1.4 step 2a */
91762306a36Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
91862306a36Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
91962306a36Sopenharmony_ci	list_add_tail(&data1.list, &datalist);
92062306a36Sopenharmony_ci	list_add_tail(&data2.list, &datalist);
92162306a36Sopenharmony_ci	list_splice_tail(addtl, &datalist);
92262306a36Sopenharmony_ci	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
92362306a36Sopenharmony_ci	if (ret)
92462306a36Sopenharmony_ci		goto out;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	/* 10.1.1.4 step 2b */
92762306a36Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
92862306a36Sopenharmony_ci		     drbg->scratchpad, drbg_blocklen(drbg));
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ciout:
93162306a36Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
93262306a36Sopenharmony_ci	return ret;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/* Hashgen defined in 10.1.1.4 */
93662306a36Sopenharmony_cistatic int drbg_hash_hashgen(struct drbg_state *drbg,
93762306a36Sopenharmony_ci			     unsigned char *buf,
93862306a36Sopenharmony_ci			     unsigned int buflen)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	int len = 0;
94162306a36Sopenharmony_ci	int ret = 0;
94262306a36Sopenharmony_ci	unsigned char *src = drbg->scratchpad;
94362306a36Sopenharmony_ci	unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
94462306a36Sopenharmony_ci	struct drbg_string data;
94562306a36Sopenharmony_ci	LIST_HEAD(datalist);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	/* 10.1.1.4 step hashgen 2 */
94862306a36Sopenharmony_ci	memcpy(src, drbg->V, drbg_statelen(drbg));
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	drbg_string_fill(&data, src, drbg_statelen(drbg));
95162306a36Sopenharmony_ci	list_add_tail(&data.list, &datalist);
95262306a36Sopenharmony_ci	while (len < buflen) {
95362306a36Sopenharmony_ci		unsigned int outlen = 0;
95462306a36Sopenharmony_ci		/* 10.1.1.4 step hashgen 4.1 */
95562306a36Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, dst, &datalist);
95662306a36Sopenharmony_ci		if (ret) {
95762306a36Sopenharmony_ci			len = ret;
95862306a36Sopenharmony_ci			goto out;
95962306a36Sopenharmony_ci		}
96062306a36Sopenharmony_ci		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
96162306a36Sopenharmony_ci			  drbg_blocklen(drbg) : (buflen - len);
96262306a36Sopenharmony_ci		/* 10.1.1.4 step hashgen 4.2 */
96362306a36Sopenharmony_ci		memcpy(buf + len, dst, outlen);
96462306a36Sopenharmony_ci		len += outlen;
96562306a36Sopenharmony_ci		/* 10.1.1.4 hashgen step 4.3 */
96662306a36Sopenharmony_ci		if (len < buflen)
96762306a36Sopenharmony_ci			crypto_inc(src, drbg_statelen(drbg));
96862306a36Sopenharmony_ci	}
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ciout:
97162306a36Sopenharmony_ci	memset(drbg->scratchpad, 0,
97262306a36Sopenharmony_ci	       (drbg_statelen(drbg) + drbg_blocklen(drbg)));
97362306a36Sopenharmony_ci	return len;
97462306a36Sopenharmony_ci}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci/* generate function for Hash DRBG as defined in  10.1.1.4 */
97762306a36Sopenharmony_cistatic int drbg_hash_generate(struct drbg_state *drbg,
97862306a36Sopenharmony_ci			      unsigned char *buf, unsigned int buflen,
97962306a36Sopenharmony_ci			      struct list_head *addtl)
98062306a36Sopenharmony_ci{
98162306a36Sopenharmony_ci	int len = 0;
98262306a36Sopenharmony_ci	int ret = 0;
98362306a36Sopenharmony_ci	union {
98462306a36Sopenharmony_ci		unsigned char req[8];
98562306a36Sopenharmony_ci		__be64 req_int;
98662306a36Sopenharmony_ci	} u;
98762306a36Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX3;
98862306a36Sopenharmony_ci	struct drbg_string data1, data2;
98962306a36Sopenharmony_ci	LIST_HEAD(datalist);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	/* 10.1.1.4 step 2 */
99262306a36Sopenharmony_ci	ret = drbg_hash_process_addtl(drbg, addtl);
99362306a36Sopenharmony_ci	if (ret)
99462306a36Sopenharmony_ci		return ret;
99562306a36Sopenharmony_ci	/* 10.1.1.4 step 3 */
99662306a36Sopenharmony_ci	len = drbg_hash_hashgen(drbg, buf, buflen);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	/* this is the value H as documented in 10.1.1.4 */
99962306a36Sopenharmony_ci	/* 10.1.1.4 step 4 */
100062306a36Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
100162306a36Sopenharmony_ci	list_add_tail(&data1.list, &datalist);
100262306a36Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
100362306a36Sopenharmony_ci	list_add_tail(&data2.list, &datalist);
100462306a36Sopenharmony_ci	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
100562306a36Sopenharmony_ci	if (ret) {
100662306a36Sopenharmony_ci		len = ret;
100762306a36Sopenharmony_ci		goto out;
100862306a36Sopenharmony_ci	}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	/* 10.1.1.4 step 5 */
101162306a36Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
101262306a36Sopenharmony_ci		     drbg->scratchpad, drbg_blocklen(drbg));
101362306a36Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
101462306a36Sopenharmony_ci		     drbg->C, drbg_statelen(drbg));
101562306a36Sopenharmony_ci	u.req_int = cpu_to_be64(drbg->reseed_ctr);
101662306a36Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ciout:
101962306a36Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
102062306a36Sopenharmony_ci	return len;
102162306a36Sopenharmony_ci}
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci/*
102462306a36Sopenharmony_ci * scratchpad usage: as update and generate are used isolated, both
102562306a36Sopenharmony_ci * can use the scratchpad
102662306a36Sopenharmony_ci */
102762306a36Sopenharmony_cistatic const struct drbg_state_ops drbg_hash_ops = {
102862306a36Sopenharmony_ci	.update		= drbg_hash_update,
102962306a36Sopenharmony_ci	.generate	= drbg_hash_generate,
103062306a36Sopenharmony_ci	.crypto_init	= drbg_init_hash_kernel,
103162306a36Sopenharmony_ci	.crypto_fini	= drbg_fini_hash_kernel,
103262306a36Sopenharmony_ci};
103362306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci/******************************************************************
103662306a36Sopenharmony_ci * Functions common for DRBG implementations
103762306a36Sopenharmony_ci ******************************************************************/
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
104062306a36Sopenharmony_ci			      int reseed, enum drbg_seed_state new_seed_state)
104162306a36Sopenharmony_ci{
104262306a36Sopenharmony_ci	int ret = drbg->d_ops->update(drbg, seed, reseed);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	if (ret)
104562306a36Sopenharmony_ci		return ret;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	drbg->seeded = new_seed_state;
104862306a36Sopenharmony_ci	drbg->last_seed_time = jiffies;
104962306a36Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 5 */
105062306a36Sopenharmony_ci	drbg->reseed_ctr = 1;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	switch (drbg->seeded) {
105362306a36Sopenharmony_ci	case DRBG_SEED_STATE_UNSEEDED:
105462306a36Sopenharmony_ci		/* Impossible, but handle it to silence compiler warnings. */
105562306a36Sopenharmony_ci		fallthrough;
105662306a36Sopenharmony_ci	case DRBG_SEED_STATE_PARTIAL:
105762306a36Sopenharmony_ci		/*
105862306a36Sopenharmony_ci		 * Require frequent reseeds until the seed source is
105962306a36Sopenharmony_ci		 * fully initialized.
106062306a36Sopenharmony_ci		 */
106162306a36Sopenharmony_ci		drbg->reseed_threshold = 50;
106262306a36Sopenharmony_ci		break;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	case DRBG_SEED_STATE_FULL:
106562306a36Sopenharmony_ci		/*
106662306a36Sopenharmony_ci		 * Seed source has become fully initialized, frequent
106762306a36Sopenharmony_ci		 * reseeds no longer required.
106862306a36Sopenharmony_ci		 */
106962306a36Sopenharmony_ci		drbg->reseed_threshold = drbg_max_requests(drbg);
107062306a36Sopenharmony_ci		break;
107162306a36Sopenharmony_ci	}
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	return ret;
107462306a36Sopenharmony_ci}
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_cistatic inline int drbg_get_random_bytes(struct drbg_state *drbg,
107762306a36Sopenharmony_ci					unsigned char *entropy,
107862306a36Sopenharmony_ci					unsigned int entropylen)
107962306a36Sopenharmony_ci{
108062306a36Sopenharmony_ci	int ret;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	do {
108362306a36Sopenharmony_ci		get_random_bytes(entropy, entropylen);
108462306a36Sopenharmony_ci		ret = drbg_fips_continuous_test(drbg, entropy);
108562306a36Sopenharmony_ci		if (ret && ret != -EAGAIN)
108662306a36Sopenharmony_ci			return ret;
108762306a36Sopenharmony_ci	} while (ret);
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	return 0;
109062306a36Sopenharmony_ci}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_cistatic int drbg_seed_from_random(struct drbg_state *drbg)
109362306a36Sopenharmony_ci{
109462306a36Sopenharmony_ci	struct drbg_string data;
109562306a36Sopenharmony_ci	LIST_HEAD(seedlist);
109662306a36Sopenharmony_ci	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
109762306a36Sopenharmony_ci	unsigned char entropy[32];
109862306a36Sopenharmony_ci	int ret;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	BUG_ON(!entropylen);
110162306a36Sopenharmony_ci	BUG_ON(entropylen > sizeof(entropy));
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	drbg_string_fill(&data, entropy, entropylen);
110462306a36Sopenharmony_ci	list_add_tail(&data.list, &seedlist);
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	ret = drbg_get_random_bytes(drbg, entropy, entropylen);
110762306a36Sopenharmony_ci	if (ret)
110862306a36Sopenharmony_ci		goto out;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ciout:
111362306a36Sopenharmony_ci	memzero_explicit(entropy, entropylen);
111462306a36Sopenharmony_ci	return ret;
111562306a36Sopenharmony_ci}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_cistatic bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	unsigned long next_reseed;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	/* Don't ever reseed from get_random_bytes() in test mode. */
112262306a36Sopenharmony_ci	if (list_empty(&drbg->test_data.list))
112362306a36Sopenharmony_ci		return false;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	/*
112662306a36Sopenharmony_ci	 * Obtain fresh entropy for the nopr DRBGs after 300s have
112762306a36Sopenharmony_ci	 * elapsed in order to still achieve sort of partial
112862306a36Sopenharmony_ci	 * prediction resistance over the time domain at least. Note
112962306a36Sopenharmony_ci	 * that the period of 300s has been chosen to match the
113062306a36Sopenharmony_ci	 * CRNG_RESEED_INTERVAL of the get_random_bytes()' chacha
113162306a36Sopenharmony_ci	 * rngs.
113262306a36Sopenharmony_ci	 */
113362306a36Sopenharmony_ci	next_reseed = drbg->last_seed_time + 300 * HZ;
113462306a36Sopenharmony_ci	return time_after(jiffies, next_reseed);
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci/*
113862306a36Sopenharmony_ci * Seeding or reseeding of the DRBG
113962306a36Sopenharmony_ci *
114062306a36Sopenharmony_ci * @drbg: DRBG state struct
114162306a36Sopenharmony_ci * @pers: personalization / additional information buffer
114262306a36Sopenharmony_ci * @reseed: 0 for initial seed process, 1 for reseeding
114362306a36Sopenharmony_ci *
114462306a36Sopenharmony_ci * return:
114562306a36Sopenharmony_ci *	0 on success
114662306a36Sopenharmony_ci *	error value otherwise
114762306a36Sopenharmony_ci */
114862306a36Sopenharmony_cistatic int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
114962306a36Sopenharmony_ci		     bool reseed)
115062306a36Sopenharmony_ci{
115162306a36Sopenharmony_ci	int ret;
115262306a36Sopenharmony_ci	unsigned char entropy[((32 + 16) * 2)];
115362306a36Sopenharmony_ci	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
115462306a36Sopenharmony_ci	struct drbg_string data1;
115562306a36Sopenharmony_ci	LIST_HEAD(seedlist);
115662306a36Sopenharmony_ci	enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	/* 9.1 / 9.2 / 9.3.1 step 3 */
115962306a36Sopenharmony_ci	if (pers && pers->len > (drbg_max_addtl(drbg))) {
116062306a36Sopenharmony_ci		pr_devel("DRBG: personalization string too long %zu\n",
116162306a36Sopenharmony_ci			 pers->len);
116262306a36Sopenharmony_ci		return -EINVAL;
116362306a36Sopenharmony_ci	}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	if (list_empty(&drbg->test_data.list)) {
116662306a36Sopenharmony_ci		drbg_string_fill(&data1, drbg->test_data.buf,
116762306a36Sopenharmony_ci				 drbg->test_data.len);
116862306a36Sopenharmony_ci		pr_devel("DRBG: using test entropy\n");
116962306a36Sopenharmony_ci	} else {
117062306a36Sopenharmony_ci		/*
117162306a36Sopenharmony_ci		 * Gather entropy equal to the security strength of the DRBG.
117262306a36Sopenharmony_ci		 * With a derivation function, a nonce is required in addition
117362306a36Sopenharmony_ci		 * to the entropy. A nonce must be at least 1/2 of the security
117462306a36Sopenharmony_ci		 * strength of the DRBG in size. Thus, entropy + nonce is 3/2
117562306a36Sopenharmony_ci		 * of the strength. The consideration of a nonce is only
117662306a36Sopenharmony_ci		 * applicable during initial seeding.
117762306a36Sopenharmony_ci		 */
117862306a36Sopenharmony_ci		BUG_ON(!entropylen);
117962306a36Sopenharmony_ci		if (!reseed)
118062306a36Sopenharmony_ci			entropylen = ((entropylen + 1) / 2) * 3;
118162306a36Sopenharmony_ci		BUG_ON((entropylen * 2) > sizeof(entropy));
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci		/* Get seed from in-kernel /dev/urandom */
118462306a36Sopenharmony_ci		if (!rng_is_initialized())
118562306a36Sopenharmony_ci			new_seed_state = DRBG_SEED_STATE_PARTIAL;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci		ret = drbg_get_random_bytes(drbg, entropy, entropylen);
118862306a36Sopenharmony_ci		if (ret)
118962306a36Sopenharmony_ci			goto out;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci		if (!drbg->jent) {
119262306a36Sopenharmony_ci			drbg_string_fill(&data1, entropy, entropylen);
119362306a36Sopenharmony_ci			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
119462306a36Sopenharmony_ci				 entropylen);
119562306a36Sopenharmony_ci		} else {
119662306a36Sopenharmony_ci			/*
119762306a36Sopenharmony_ci			 * Get seed from Jitter RNG, failures are
119862306a36Sopenharmony_ci			 * fatal only in FIPS mode.
119962306a36Sopenharmony_ci			 */
120062306a36Sopenharmony_ci			ret = crypto_rng_get_bytes(drbg->jent,
120162306a36Sopenharmony_ci						   entropy + entropylen,
120262306a36Sopenharmony_ci						   entropylen);
120362306a36Sopenharmony_ci			if (fips_enabled && ret) {
120462306a36Sopenharmony_ci				pr_devel("DRBG: jent failed with %d\n", ret);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci				/*
120762306a36Sopenharmony_ci				 * Do not treat the transient failure of the
120862306a36Sopenharmony_ci				 * Jitter RNG as an error that needs to be
120962306a36Sopenharmony_ci				 * reported. The combined number of the
121062306a36Sopenharmony_ci				 * maximum reseed threshold times the maximum
121162306a36Sopenharmony_ci				 * number of Jitter RNG transient errors is
121262306a36Sopenharmony_ci				 * less than the reseed threshold required by
121362306a36Sopenharmony_ci				 * SP800-90A allowing us to treat the
121462306a36Sopenharmony_ci				 * transient errors as such.
121562306a36Sopenharmony_ci				 *
121662306a36Sopenharmony_ci				 * However, we mandate that at least the first
121762306a36Sopenharmony_ci				 * seeding operation must succeed with the
121862306a36Sopenharmony_ci				 * Jitter RNG.
121962306a36Sopenharmony_ci				 */
122062306a36Sopenharmony_ci				if (!reseed || ret != -EAGAIN)
122162306a36Sopenharmony_ci					goto out;
122262306a36Sopenharmony_ci			}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci			drbg_string_fill(&data1, entropy, entropylen * 2);
122562306a36Sopenharmony_ci			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
122662306a36Sopenharmony_ci				 entropylen * 2);
122762306a36Sopenharmony_ci		}
122862306a36Sopenharmony_ci	}
122962306a36Sopenharmony_ci	list_add_tail(&data1.list, &seedlist);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	/*
123262306a36Sopenharmony_ci	 * concatenation of entropy with personalization str / addtl input)
123362306a36Sopenharmony_ci	 * the variable pers is directly handed in by the caller, so check its
123462306a36Sopenharmony_ci	 * contents whether it is appropriate
123562306a36Sopenharmony_ci	 */
123662306a36Sopenharmony_ci	if (pers && pers->buf && 0 < pers->len) {
123762306a36Sopenharmony_ci		list_add_tail(&pers->list, &seedlist);
123862306a36Sopenharmony_ci		pr_devel("DRBG: using personalization string\n");
123962306a36Sopenharmony_ci	}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	if (!reseed) {
124262306a36Sopenharmony_ci		memset(drbg->V, 0, drbg_statelen(drbg));
124362306a36Sopenharmony_ci		memset(drbg->C, 0, drbg_statelen(drbg));
124462306a36Sopenharmony_ci	}
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ciout:
124962306a36Sopenharmony_ci	memzero_explicit(entropy, entropylen * 2);
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	return ret;
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci/* Free all substructures in a DRBG state without the DRBG state structure */
125562306a36Sopenharmony_cistatic inline void drbg_dealloc_state(struct drbg_state *drbg)
125662306a36Sopenharmony_ci{
125762306a36Sopenharmony_ci	if (!drbg)
125862306a36Sopenharmony_ci		return;
125962306a36Sopenharmony_ci	kfree_sensitive(drbg->Vbuf);
126062306a36Sopenharmony_ci	drbg->Vbuf = NULL;
126162306a36Sopenharmony_ci	drbg->V = NULL;
126262306a36Sopenharmony_ci	kfree_sensitive(drbg->Cbuf);
126362306a36Sopenharmony_ci	drbg->Cbuf = NULL;
126462306a36Sopenharmony_ci	drbg->C = NULL;
126562306a36Sopenharmony_ci	kfree_sensitive(drbg->scratchpadbuf);
126662306a36Sopenharmony_ci	drbg->scratchpadbuf = NULL;
126762306a36Sopenharmony_ci	drbg->reseed_ctr = 0;
126862306a36Sopenharmony_ci	drbg->d_ops = NULL;
126962306a36Sopenharmony_ci	drbg->core = NULL;
127062306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
127162306a36Sopenharmony_ci		kfree_sensitive(drbg->prev);
127262306a36Sopenharmony_ci		drbg->prev = NULL;
127362306a36Sopenharmony_ci		drbg->fips_primed = false;
127462306a36Sopenharmony_ci	}
127562306a36Sopenharmony_ci}
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci/*
127862306a36Sopenharmony_ci * Allocate all sub-structures for a DRBG state.
127962306a36Sopenharmony_ci * The DRBG state structure must already be allocated.
128062306a36Sopenharmony_ci */
128162306a36Sopenharmony_cistatic inline int drbg_alloc_state(struct drbg_state *drbg)
128262306a36Sopenharmony_ci{
128362306a36Sopenharmony_ci	int ret = -ENOMEM;
128462306a36Sopenharmony_ci	unsigned int sb_size = 0;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	switch (drbg->core->flags & DRBG_TYPE_MASK) {
128762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
128862306a36Sopenharmony_ci	case DRBG_HMAC:
128962306a36Sopenharmony_ci		drbg->d_ops = &drbg_hmac_ops;
129062306a36Sopenharmony_ci		break;
129162306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
129262306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
129362306a36Sopenharmony_ci	case DRBG_HASH:
129462306a36Sopenharmony_ci		drbg->d_ops = &drbg_hash_ops;
129562306a36Sopenharmony_ci		break;
129662306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
129762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
129862306a36Sopenharmony_ci	case DRBG_CTR:
129962306a36Sopenharmony_ci		drbg->d_ops = &drbg_ctr_ops;
130062306a36Sopenharmony_ci		break;
130162306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
130262306a36Sopenharmony_ci	default:
130362306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
130462306a36Sopenharmony_ci		goto err;
130562306a36Sopenharmony_ci	}
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	ret = drbg->d_ops->crypto_init(drbg);
130862306a36Sopenharmony_ci	if (ret < 0)
130962306a36Sopenharmony_ci		goto err;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
131262306a36Sopenharmony_ci	if (!drbg->Vbuf) {
131362306a36Sopenharmony_ci		ret = -ENOMEM;
131462306a36Sopenharmony_ci		goto fini;
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci	drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
131762306a36Sopenharmony_ci	drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
131862306a36Sopenharmony_ci	if (!drbg->Cbuf) {
131962306a36Sopenharmony_ci		ret = -ENOMEM;
132062306a36Sopenharmony_ci		goto fini;
132162306a36Sopenharmony_ci	}
132262306a36Sopenharmony_ci	drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
132362306a36Sopenharmony_ci	/* scratchpad is only generated for CTR and Hash */
132462306a36Sopenharmony_ci	if (drbg->core->flags & DRBG_HMAC)
132562306a36Sopenharmony_ci		sb_size = 0;
132662306a36Sopenharmony_ci	else if (drbg->core->flags & DRBG_CTR)
132762306a36Sopenharmony_ci		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
132862306a36Sopenharmony_ci			  drbg_statelen(drbg) +	/* df_data */
132962306a36Sopenharmony_ci			  drbg_blocklen(drbg) +	/* pad */
133062306a36Sopenharmony_ci			  drbg_blocklen(drbg) +	/* iv */
133162306a36Sopenharmony_ci			  drbg_statelen(drbg) + drbg_blocklen(drbg); /* temp */
133262306a36Sopenharmony_ci	else
133362306a36Sopenharmony_ci		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	if (0 < sb_size) {
133662306a36Sopenharmony_ci		drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL);
133762306a36Sopenharmony_ci		if (!drbg->scratchpadbuf) {
133862306a36Sopenharmony_ci			ret = -ENOMEM;
133962306a36Sopenharmony_ci			goto fini;
134062306a36Sopenharmony_ci		}
134162306a36Sopenharmony_ci		drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
134262306a36Sopenharmony_ci	}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
134562306a36Sopenharmony_ci		drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
134662306a36Sopenharmony_ci				     GFP_KERNEL);
134762306a36Sopenharmony_ci		if (!drbg->prev) {
134862306a36Sopenharmony_ci			ret = -ENOMEM;
134962306a36Sopenharmony_ci			goto fini;
135062306a36Sopenharmony_ci		}
135162306a36Sopenharmony_ci		drbg->fips_primed = false;
135262306a36Sopenharmony_ci	}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	return 0;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_cifini:
135762306a36Sopenharmony_ci	drbg->d_ops->crypto_fini(drbg);
135862306a36Sopenharmony_cierr:
135962306a36Sopenharmony_ci	drbg_dealloc_state(drbg);
136062306a36Sopenharmony_ci	return ret;
136162306a36Sopenharmony_ci}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci/*************************************************************************
136462306a36Sopenharmony_ci * DRBG interface functions
136562306a36Sopenharmony_ci *************************************************************************/
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci/*
136862306a36Sopenharmony_ci * DRBG generate function as required by SP800-90A - this function
136962306a36Sopenharmony_ci * generates random numbers
137062306a36Sopenharmony_ci *
137162306a36Sopenharmony_ci * @drbg DRBG state handle
137262306a36Sopenharmony_ci * @buf Buffer where to store the random numbers -- the buffer must already
137362306a36Sopenharmony_ci *      be pre-allocated by caller
137462306a36Sopenharmony_ci * @buflen Length of output buffer - this value defines the number of random
137562306a36Sopenharmony_ci *	   bytes pulled from DRBG
137662306a36Sopenharmony_ci * @addtl Additional input that is mixed into state, may be NULL -- note
137762306a36Sopenharmony_ci *	  the entropy is pulled by the DRBG internally unconditionally
137862306a36Sopenharmony_ci *	  as defined in SP800-90A. The additional input is mixed into
137962306a36Sopenharmony_ci *	  the state in addition to the pulled entropy.
138062306a36Sopenharmony_ci *
138162306a36Sopenharmony_ci * return: 0 when all bytes are generated; < 0 in case of an error
138262306a36Sopenharmony_ci */
138362306a36Sopenharmony_cistatic int drbg_generate(struct drbg_state *drbg,
138462306a36Sopenharmony_ci			 unsigned char *buf, unsigned int buflen,
138562306a36Sopenharmony_ci			 struct drbg_string *addtl)
138662306a36Sopenharmony_ci{
138762306a36Sopenharmony_ci	int len = 0;
138862306a36Sopenharmony_ci	LIST_HEAD(addtllist);
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (!drbg->core) {
139162306a36Sopenharmony_ci		pr_devel("DRBG: not yet seeded\n");
139262306a36Sopenharmony_ci		return -EINVAL;
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci	if (0 == buflen || !buf) {
139562306a36Sopenharmony_ci		pr_devel("DRBG: no output buffer provided\n");
139662306a36Sopenharmony_ci		return -EINVAL;
139762306a36Sopenharmony_ci	}
139862306a36Sopenharmony_ci	if (addtl && NULL == addtl->buf && 0 < addtl->len) {
139962306a36Sopenharmony_ci		pr_devel("DRBG: wrong format of additional information\n");
140062306a36Sopenharmony_ci		return -EINVAL;
140162306a36Sopenharmony_ci	}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	/* 9.3.1 step 2 */
140462306a36Sopenharmony_ci	len = -EINVAL;
140562306a36Sopenharmony_ci	if (buflen > (drbg_max_request_bytes(drbg))) {
140662306a36Sopenharmony_ci		pr_devel("DRBG: requested random numbers too large %u\n",
140762306a36Sopenharmony_ci			 buflen);
140862306a36Sopenharmony_ci		goto err;
140962306a36Sopenharmony_ci	}
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	/* 9.3.1 step 3 is implicit with the chosen DRBG */
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	/* 9.3.1 step 4 */
141462306a36Sopenharmony_ci	if (addtl && addtl->len > (drbg_max_addtl(drbg))) {
141562306a36Sopenharmony_ci		pr_devel("DRBG: additional information string too long %zu\n",
141662306a36Sopenharmony_ci			 addtl->len);
141762306a36Sopenharmony_ci		goto err;
141862306a36Sopenharmony_ci	}
141962306a36Sopenharmony_ci	/* 9.3.1 step 5 is implicit with the chosen DRBG */
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	/*
142262306a36Sopenharmony_ci	 * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented
142362306a36Sopenharmony_ci	 * here. The spec is a bit convoluted here, we make it simpler.
142462306a36Sopenharmony_ci	 */
142562306a36Sopenharmony_ci	if (drbg->reseed_threshold < drbg->reseed_ctr)
142662306a36Sopenharmony_ci		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
142962306a36Sopenharmony_ci		pr_devel("DRBG: reseeding before generation (prediction "
143062306a36Sopenharmony_ci			 "resistance: %s, state %s)\n",
143162306a36Sopenharmony_ci			 drbg->pr ? "true" : "false",
143262306a36Sopenharmony_ci			 (drbg->seeded ==  DRBG_SEED_STATE_FULL ?
143362306a36Sopenharmony_ci			  "seeded" : "unseeded"));
143462306a36Sopenharmony_ci		/* 9.3.1 steps 7.1 through 7.3 */
143562306a36Sopenharmony_ci		len = drbg_seed(drbg, addtl, true);
143662306a36Sopenharmony_ci		if (len)
143762306a36Sopenharmony_ci			goto err;
143862306a36Sopenharmony_ci		/* 9.3.1 step 7.4 */
143962306a36Sopenharmony_ci		addtl = NULL;
144062306a36Sopenharmony_ci	} else if (rng_is_initialized() &&
144162306a36Sopenharmony_ci		   (drbg->seeded == DRBG_SEED_STATE_PARTIAL ||
144262306a36Sopenharmony_ci		    drbg_nopr_reseed_interval_elapsed(drbg))) {
144362306a36Sopenharmony_ci		len = drbg_seed_from_random(drbg);
144462306a36Sopenharmony_ci		if (len)
144562306a36Sopenharmony_ci			goto err;
144662306a36Sopenharmony_ci	}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (addtl && 0 < addtl->len)
144962306a36Sopenharmony_ci		list_add_tail(&addtl->list, &addtllist);
145062306a36Sopenharmony_ci	/* 9.3.1 step 8 and 10 */
145162306a36Sopenharmony_ci	len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist);
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci	/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
145462306a36Sopenharmony_ci	drbg->reseed_ctr++;
145562306a36Sopenharmony_ci	if (0 >= len)
145662306a36Sopenharmony_ci		goto err;
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	/*
145962306a36Sopenharmony_ci	 * Section 11.3.3 requires to re-perform self tests after some
146062306a36Sopenharmony_ci	 * generated random numbers. The chosen value after which self
146162306a36Sopenharmony_ci	 * test is performed is arbitrary, but it should be reasonable.
146262306a36Sopenharmony_ci	 * However, we do not perform the self tests because of the following
146362306a36Sopenharmony_ci	 * reasons: it is mathematically impossible that the initial self tests
146462306a36Sopenharmony_ci	 * were successfully and the following are not. If the initial would
146562306a36Sopenharmony_ci	 * pass and the following would not, the kernel integrity is violated.
146662306a36Sopenharmony_ci	 * In this case, the entire kernel operation is questionable and it
146762306a36Sopenharmony_ci	 * is unlikely that the integrity violation only affects the
146862306a36Sopenharmony_ci	 * correct operation of the DRBG.
146962306a36Sopenharmony_ci	 *
147062306a36Sopenharmony_ci	 * Albeit the following code is commented out, it is provided in
147162306a36Sopenharmony_ci	 * case somebody has a need to implement the test of 11.3.3.
147262306a36Sopenharmony_ci	 */
147362306a36Sopenharmony_ci#if 0
147462306a36Sopenharmony_ci	if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) {
147562306a36Sopenharmony_ci		int err = 0;
147662306a36Sopenharmony_ci		pr_devel("DRBG: start to perform self test\n");
147762306a36Sopenharmony_ci		if (drbg->core->flags & DRBG_HMAC)
147862306a36Sopenharmony_ci			err = alg_test("drbg_pr_hmac_sha256",
147962306a36Sopenharmony_ci				       "drbg_pr_hmac_sha256", 0, 0);
148062306a36Sopenharmony_ci		else if (drbg->core->flags & DRBG_CTR)
148162306a36Sopenharmony_ci			err = alg_test("drbg_pr_ctr_aes128",
148262306a36Sopenharmony_ci				       "drbg_pr_ctr_aes128", 0, 0);
148362306a36Sopenharmony_ci		else
148462306a36Sopenharmony_ci			err = alg_test("drbg_pr_sha256",
148562306a36Sopenharmony_ci				       "drbg_pr_sha256", 0, 0);
148662306a36Sopenharmony_ci		if (err) {
148762306a36Sopenharmony_ci			pr_err("DRBG: periodical self test failed\n");
148862306a36Sopenharmony_ci			/*
148962306a36Sopenharmony_ci			 * uninstantiate implies that from now on, only errors
149062306a36Sopenharmony_ci			 * are returned when reusing this DRBG cipher handle
149162306a36Sopenharmony_ci			 */
149262306a36Sopenharmony_ci			drbg_uninstantiate(drbg);
149362306a36Sopenharmony_ci			return 0;
149462306a36Sopenharmony_ci		} else {
149562306a36Sopenharmony_ci			pr_devel("DRBG: self test successful\n");
149662306a36Sopenharmony_ci		}
149762306a36Sopenharmony_ci	}
149862306a36Sopenharmony_ci#endif
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	/*
150162306a36Sopenharmony_ci	 * All operations were successful, return 0 as mandated by
150262306a36Sopenharmony_ci	 * the kernel crypto API interface.
150362306a36Sopenharmony_ci	 */
150462306a36Sopenharmony_ci	len = 0;
150562306a36Sopenharmony_cierr:
150662306a36Sopenharmony_ci	return len;
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci/*
151062306a36Sopenharmony_ci * Wrapper around drbg_generate which can pull arbitrary long strings
151162306a36Sopenharmony_ci * from the DRBG without hitting the maximum request limitation.
151262306a36Sopenharmony_ci *
151362306a36Sopenharmony_ci * Parameters: see drbg_generate
151462306a36Sopenharmony_ci * Return codes: see drbg_generate -- if one drbg_generate request fails,
151562306a36Sopenharmony_ci *		 the entire drbg_generate_long request fails
151662306a36Sopenharmony_ci */
151762306a36Sopenharmony_cistatic int drbg_generate_long(struct drbg_state *drbg,
151862306a36Sopenharmony_ci			      unsigned char *buf, unsigned int buflen,
151962306a36Sopenharmony_ci			      struct drbg_string *addtl)
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	unsigned int len = 0;
152262306a36Sopenharmony_ci	unsigned int slice = 0;
152362306a36Sopenharmony_ci	do {
152462306a36Sopenharmony_ci		int err = 0;
152562306a36Sopenharmony_ci		unsigned int chunk = 0;
152662306a36Sopenharmony_ci		slice = ((buflen - len) / drbg_max_request_bytes(drbg));
152762306a36Sopenharmony_ci		chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
152862306a36Sopenharmony_ci		mutex_lock(&drbg->drbg_mutex);
152962306a36Sopenharmony_ci		err = drbg_generate(drbg, buf + len, chunk, addtl);
153062306a36Sopenharmony_ci		mutex_unlock(&drbg->drbg_mutex);
153162306a36Sopenharmony_ci		if (0 > err)
153262306a36Sopenharmony_ci			return err;
153362306a36Sopenharmony_ci		len += chunk;
153462306a36Sopenharmony_ci	} while (slice > 0 && (len < buflen));
153562306a36Sopenharmony_ci	return 0;
153662306a36Sopenharmony_ci}
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_cistatic int drbg_prepare_hrng(struct drbg_state *drbg)
153962306a36Sopenharmony_ci{
154062306a36Sopenharmony_ci	/* We do not need an HRNG in test mode. */
154162306a36Sopenharmony_ci	if (list_empty(&drbg->test_data.list))
154262306a36Sopenharmony_ci		return 0;
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci	drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
154562306a36Sopenharmony_ci	if (IS_ERR(drbg->jent)) {
154662306a36Sopenharmony_ci		const int err = PTR_ERR(drbg->jent);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci		drbg->jent = NULL;
154962306a36Sopenharmony_ci		if (fips_enabled)
155062306a36Sopenharmony_ci			return err;
155162306a36Sopenharmony_ci		pr_info("DRBG: Continuing without Jitter RNG\n");
155262306a36Sopenharmony_ci	}
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	return 0;
155562306a36Sopenharmony_ci}
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci/*
155862306a36Sopenharmony_ci * DRBG instantiation function as required by SP800-90A - this function
155962306a36Sopenharmony_ci * sets up the DRBG handle, performs the initial seeding and all sanity
156062306a36Sopenharmony_ci * checks required by SP800-90A
156162306a36Sopenharmony_ci *
156262306a36Sopenharmony_ci * @drbg memory of state -- if NULL, new memory is allocated
156362306a36Sopenharmony_ci * @pers Personalization string that is mixed into state, may be NULL -- note
156462306a36Sopenharmony_ci *	 the entropy is pulled by the DRBG internally unconditionally
156562306a36Sopenharmony_ci *	 as defined in SP800-90A. The additional input is mixed into
156662306a36Sopenharmony_ci *	 the state in addition to the pulled entropy.
156762306a36Sopenharmony_ci * @coreref reference to core
156862306a36Sopenharmony_ci * @pr prediction resistance enabled
156962306a36Sopenharmony_ci *
157062306a36Sopenharmony_ci * return
157162306a36Sopenharmony_ci *	0 on success
157262306a36Sopenharmony_ci *	error value otherwise
157362306a36Sopenharmony_ci */
157462306a36Sopenharmony_cistatic int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
157562306a36Sopenharmony_ci			    int coreref, bool pr)
157662306a36Sopenharmony_ci{
157762306a36Sopenharmony_ci	int ret;
157862306a36Sopenharmony_ci	bool reseed = true;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
158162306a36Sopenharmony_ci		 "%s\n", coreref, pr ? "enabled" : "disabled");
158262306a36Sopenharmony_ci	mutex_lock(&drbg->drbg_mutex);
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	/* 9.1 step 1 is implicit with the selected DRBG type */
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	/*
158762306a36Sopenharmony_ci	 * 9.1 step 2 is implicit as caller can select prediction resistance
158862306a36Sopenharmony_ci	 * and the flag is copied into drbg->flags --
158962306a36Sopenharmony_ci	 * all DRBG types support prediction resistance
159062306a36Sopenharmony_ci	 */
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	/* 9.1 step 4 is implicit in  drbg_sec_strength */
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	if (!drbg->core) {
159562306a36Sopenharmony_ci		drbg->core = &drbg_cores[coreref];
159662306a36Sopenharmony_ci		drbg->pr = pr;
159762306a36Sopenharmony_ci		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
159862306a36Sopenharmony_ci		drbg->last_seed_time = 0;
159962306a36Sopenharmony_ci		drbg->reseed_threshold = drbg_max_requests(drbg);
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci		ret = drbg_alloc_state(drbg);
160262306a36Sopenharmony_ci		if (ret)
160362306a36Sopenharmony_ci			goto unlock;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci		ret = drbg_prepare_hrng(drbg);
160662306a36Sopenharmony_ci		if (ret)
160762306a36Sopenharmony_ci			goto free_everything;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci		reseed = false;
161062306a36Sopenharmony_ci	}
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	ret = drbg_seed(drbg, pers, reseed);
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	if (ret && !reseed)
161562306a36Sopenharmony_ci		goto free_everything;
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
161862306a36Sopenharmony_ci	return ret;
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ciunlock:
162162306a36Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
162262306a36Sopenharmony_ci	return ret;
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_cifree_everything:
162562306a36Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
162662306a36Sopenharmony_ci	drbg_uninstantiate(drbg);
162762306a36Sopenharmony_ci	return ret;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci/*
163162306a36Sopenharmony_ci * DRBG uninstantiate function as required by SP800-90A - this function
163262306a36Sopenharmony_ci * frees all buffers and the DRBG handle
163362306a36Sopenharmony_ci *
163462306a36Sopenharmony_ci * @drbg DRBG state handle
163562306a36Sopenharmony_ci *
163662306a36Sopenharmony_ci * return
163762306a36Sopenharmony_ci *	0 on success
163862306a36Sopenharmony_ci */
163962306a36Sopenharmony_cistatic int drbg_uninstantiate(struct drbg_state *drbg)
164062306a36Sopenharmony_ci{
164162306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(drbg->jent))
164262306a36Sopenharmony_ci		crypto_free_rng(drbg->jent);
164362306a36Sopenharmony_ci	drbg->jent = NULL;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	if (drbg->d_ops)
164662306a36Sopenharmony_ci		drbg->d_ops->crypto_fini(drbg);
164762306a36Sopenharmony_ci	drbg_dealloc_state(drbg);
164862306a36Sopenharmony_ci	/* no scrubbing of test_data -- this shall survive an uninstantiate */
164962306a36Sopenharmony_ci	return 0;
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci/*
165362306a36Sopenharmony_ci * Helper function for setting the test data in the DRBG
165462306a36Sopenharmony_ci *
165562306a36Sopenharmony_ci * @drbg DRBG state handle
165662306a36Sopenharmony_ci * @data test data
165762306a36Sopenharmony_ci * @len test data length
165862306a36Sopenharmony_ci */
165962306a36Sopenharmony_cistatic void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
166062306a36Sopenharmony_ci				   const u8 *data, unsigned int len)
166162306a36Sopenharmony_ci{
166262306a36Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	mutex_lock(&drbg->drbg_mutex);
166562306a36Sopenharmony_ci	drbg_string_fill(&drbg->test_data, data, len);
166662306a36Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
166762306a36Sopenharmony_ci}
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci/***************************************************************
167062306a36Sopenharmony_ci * Kernel crypto API cipher invocations requested by DRBG
167162306a36Sopenharmony_ci ***************************************************************/
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
167462306a36Sopenharmony_cistruct sdesc {
167562306a36Sopenharmony_ci	struct shash_desc shash;
167662306a36Sopenharmony_ci	char ctx[];
167762306a36Sopenharmony_ci};
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_cistatic int drbg_init_hash_kernel(struct drbg_state *drbg)
168062306a36Sopenharmony_ci{
168162306a36Sopenharmony_ci	struct sdesc *sdesc;
168262306a36Sopenharmony_ci	struct crypto_shash *tfm;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
168562306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
168662306a36Sopenharmony_ci		pr_info("DRBG: could not allocate digest TFM handle: %s\n",
168762306a36Sopenharmony_ci				drbg->core->backend_cra_name);
168862306a36Sopenharmony_ci		return PTR_ERR(tfm);
168962306a36Sopenharmony_ci	}
169062306a36Sopenharmony_ci	BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
169162306a36Sopenharmony_ci	sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
169262306a36Sopenharmony_ci			GFP_KERNEL);
169362306a36Sopenharmony_ci	if (!sdesc) {
169462306a36Sopenharmony_ci		crypto_free_shash(tfm);
169562306a36Sopenharmony_ci		return -ENOMEM;
169662306a36Sopenharmony_ci	}
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	sdesc->shash.tfm = tfm;
169962306a36Sopenharmony_ci	drbg->priv_data = sdesc;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	return crypto_shash_alignmask(tfm);
170262306a36Sopenharmony_ci}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_cistatic int drbg_fini_hash_kernel(struct drbg_state *drbg)
170562306a36Sopenharmony_ci{
170662306a36Sopenharmony_ci	struct sdesc *sdesc = drbg->priv_data;
170762306a36Sopenharmony_ci	if (sdesc) {
170862306a36Sopenharmony_ci		crypto_free_shash(sdesc->shash.tfm);
170962306a36Sopenharmony_ci		kfree_sensitive(sdesc);
171062306a36Sopenharmony_ci	}
171162306a36Sopenharmony_ci	drbg->priv_data = NULL;
171262306a36Sopenharmony_ci	return 0;
171362306a36Sopenharmony_ci}
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_cistatic void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
171662306a36Sopenharmony_ci				  const unsigned char *key)
171762306a36Sopenharmony_ci{
171862306a36Sopenharmony_ci	struct sdesc *sdesc = drbg->priv_data;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
172162306a36Sopenharmony_ci}
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_cistatic int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
172462306a36Sopenharmony_ci			   const struct list_head *in)
172562306a36Sopenharmony_ci{
172662306a36Sopenharmony_ci	struct sdesc *sdesc = drbg->priv_data;
172762306a36Sopenharmony_ci	struct drbg_string *input = NULL;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	crypto_shash_init(&sdesc->shash);
173062306a36Sopenharmony_ci	list_for_each_entry(input, in, list)
173162306a36Sopenharmony_ci		crypto_shash_update(&sdesc->shash, input->buf, input->len);
173262306a36Sopenharmony_ci	return crypto_shash_final(&sdesc->shash, outval);
173362306a36Sopenharmony_ci}
173462306a36Sopenharmony_ci#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
173762306a36Sopenharmony_cistatic int drbg_fini_sym_kernel(struct drbg_state *drbg)
173862306a36Sopenharmony_ci{
173962306a36Sopenharmony_ci	struct crypto_cipher *tfm =
174062306a36Sopenharmony_ci		(struct crypto_cipher *)drbg->priv_data;
174162306a36Sopenharmony_ci	if (tfm)
174262306a36Sopenharmony_ci		crypto_free_cipher(tfm);
174362306a36Sopenharmony_ci	drbg->priv_data = NULL;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	if (drbg->ctr_handle)
174662306a36Sopenharmony_ci		crypto_free_skcipher(drbg->ctr_handle);
174762306a36Sopenharmony_ci	drbg->ctr_handle = NULL;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	if (drbg->ctr_req)
175062306a36Sopenharmony_ci		skcipher_request_free(drbg->ctr_req);
175162306a36Sopenharmony_ci	drbg->ctr_req = NULL;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	kfree(drbg->outscratchpadbuf);
175462306a36Sopenharmony_ci	drbg->outscratchpadbuf = NULL;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	return 0;
175762306a36Sopenharmony_ci}
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_cistatic int drbg_init_sym_kernel(struct drbg_state *drbg)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	struct crypto_cipher *tfm;
176262306a36Sopenharmony_ci	struct crypto_skcipher *sk_tfm;
176362306a36Sopenharmony_ci	struct skcipher_request *req;
176462306a36Sopenharmony_ci	unsigned int alignmask;
176562306a36Sopenharmony_ci	char ctr_name[CRYPTO_MAX_ALG_NAME];
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0);
176862306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
176962306a36Sopenharmony_ci		pr_info("DRBG: could not allocate cipher TFM handle: %s\n",
177062306a36Sopenharmony_ci				drbg->core->backend_cra_name);
177162306a36Sopenharmony_ci		return PTR_ERR(tfm);
177262306a36Sopenharmony_ci	}
177362306a36Sopenharmony_ci	BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm));
177462306a36Sopenharmony_ci	drbg->priv_data = tfm;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
177762306a36Sopenharmony_ci	    drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) {
177862306a36Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
177962306a36Sopenharmony_ci		return -EINVAL;
178062306a36Sopenharmony_ci	}
178162306a36Sopenharmony_ci	sk_tfm = crypto_alloc_skcipher(ctr_name, 0, 0);
178262306a36Sopenharmony_ci	if (IS_ERR(sk_tfm)) {
178362306a36Sopenharmony_ci		pr_info("DRBG: could not allocate CTR cipher TFM handle: %s\n",
178462306a36Sopenharmony_ci				ctr_name);
178562306a36Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
178662306a36Sopenharmony_ci		return PTR_ERR(sk_tfm);
178762306a36Sopenharmony_ci	}
178862306a36Sopenharmony_ci	drbg->ctr_handle = sk_tfm;
178962306a36Sopenharmony_ci	crypto_init_wait(&drbg->ctr_wait);
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	req = skcipher_request_alloc(sk_tfm, GFP_KERNEL);
179262306a36Sopenharmony_ci	if (!req) {
179362306a36Sopenharmony_ci		pr_info("DRBG: could not allocate request queue\n");
179462306a36Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
179562306a36Sopenharmony_ci		return -ENOMEM;
179662306a36Sopenharmony_ci	}
179762306a36Sopenharmony_ci	drbg->ctr_req = req;
179862306a36Sopenharmony_ci	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
179962306a36Sopenharmony_ci						CRYPTO_TFM_REQ_MAY_SLEEP,
180062306a36Sopenharmony_ci					crypto_req_done, &drbg->ctr_wait);
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	alignmask = crypto_skcipher_alignmask(sk_tfm);
180362306a36Sopenharmony_ci	drbg->outscratchpadbuf = kmalloc(DRBG_OUTSCRATCHLEN + alignmask,
180462306a36Sopenharmony_ci					 GFP_KERNEL);
180562306a36Sopenharmony_ci	if (!drbg->outscratchpadbuf) {
180662306a36Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
180762306a36Sopenharmony_ci		return -ENOMEM;
180862306a36Sopenharmony_ci	}
180962306a36Sopenharmony_ci	drbg->outscratchpad = (u8 *)PTR_ALIGN(drbg->outscratchpadbuf,
181062306a36Sopenharmony_ci					      alignmask + 1);
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	sg_init_table(&drbg->sg_in, 1);
181362306a36Sopenharmony_ci	sg_init_one(&drbg->sg_out, drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	return alignmask;
181662306a36Sopenharmony_ci}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_cistatic void drbg_kcapi_symsetkey(struct drbg_state *drbg,
181962306a36Sopenharmony_ci				 const unsigned char *key)
182062306a36Sopenharmony_ci{
182162306a36Sopenharmony_ci	struct crypto_cipher *tfm = drbg->priv_data;
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	crypto_cipher_setkey(tfm, key, (drbg_keylen(drbg)));
182462306a36Sopenharmony_ci}
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_cistatic int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
182762306a36Sopenharmony_ci			  const struct drbg_string *in)
182862306a36Sopenharmony_ci{
182962306a36Sopenharmony_ci	struct crypto_cipher *tfm = drbg->priv_data;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	/* there is only component in *in */
183262306a36Sopenharmony_ci	BUG_ON(in->len < drbg_blocklen(drbg));
183362306a36Sopenharmony_ci	crypto_cipher_encrypt_one(tfm, outval, in->buf);
183462306a36Sopenharmony_ci	return 0;
183562306a36Sopenharmony_ci}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_cistatic int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
183862306a36Sopenharmony_ci			      u8 *inbuf, u32 inlen,
183962306a36Sopenharmony_ci			      u8 *outbuf, u32 outlen)
184062306a36Sopenharmony_ci{
184162306a36Sopenharmony_ci	struct scatterlist *sg_in = &drbg->sg_in, *sg_out = &drbg->sg_out;
184262306a36Sopenharmony_ci	u32 scratchpad_use = min_t(u32, outlen, DRBG_OUTSCRATCHLEN);
184362306a36Sopenharmony_ci	int ret;
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	if (inbuf) {
184662306a36Sopenharmony_ci		/* Use caller-provided input buffer */
184762306a36Sopenharmony_ci		sg_set_buf(sg_in, inbuf, inlen);
184862306a36Sopenharmony_ci	} else {
184962306a36Sopenharmony_ci		/* Use scratchpad for in-place operation */
185062306a36Sopenharmony_ci		inlen = scratchpad_use;
185162306a36Sopenharmony_ci		memset(drbg->outscratchpad, 0, scratchpad_use);
185262306a36Sopenharmony_ci		sg_set_buf(sg_in, drbg->outscratchpad, scratchpad_use);
185362306a36Sopenharmony_ci	}
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	while (outlen) {
185662306a36Sopenharmony_ci		u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN);
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci		/* Output buffer may not be valid for SGL, use scratchpad */
185962306a36Sopenharmony_ci		skcipher_request_set_crypt(drbg->ctr_req, sg_in, sg_out,
186062306a36Sopenharmony_ci					   cryptlen, drbg->V);
186162306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req),
186262306a36Sopenharmony_ci					&drbg->ctr_wait);
186362306a36Sopenharmony_ci		if (ret)
186462306a36Sopenharmony_ci			goto out;
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci		crypto_init_wait(&drbg->ctr_wait);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci		memcpy(outbuf, drbg->outscratchpad, cryptlen);
186962306a36Sopenharmony_ci		memzero_explicit(drbg->outscratchpad, cryptlen);
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci		outlen -= cryptlen;
187262306a36Sopenharmony_ci		outbuf += cryptlen;
187362306a36Sopenharmony_ci	}
187462306a36Sopenharmony_ci	ret = 0;
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ciout:
187762306a36Sopenharmony_ci	return ret;
187862306a36Sopenharmony_ci}
187962306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci/***************************************************************
188262306a36Sopenharmony_ci * Kernel crypto API interface to register DRBG
188362306a36Sopenharmony_ci ***************************************************************/
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci/*
188662306a36Sopenharmony_ci * Look up the DRBG flags by given kernel crypto API cra_name
188762306a36Sopenharmony_ci * The code uses the drbg_cores definition to do this
188862306a36Sopenharmony_ci *
188962306a36Sopenharmony_ci * @cra_name kernel crypto API cra_name
189062306a36Sopenharmony_ci * @coreref reference to integer which is filled with the pointer to
189162306a36Sopenharmony_ci *  the applicable core
189262306a36Sopenharmony_ci * @pr reference for setting prediction resistance
189362306a36Sopenharmony_ci *
189462306a36Sopenharmony_ci * return: flags
189562306a36Sopenharmony_ci */
189662306a36Sopenharmony_cistatic inline void drbg_convert_tfm_core(const char *cra_driver_name,
189762306a36Sopenharmony_ci					 int *coreref, bool *pr)
189862306a36Sopenharmony_ci{
189962306a36Sopenharmony_ci	int i = 0;
190062306a36Sopenharmony_ci	size_t start = 0;
190162306a36Sopenharmony_ci	int len = 0;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	*pr = true;
190462306a36Sopenharmony_ci	/* disassemble the names */
190562306a36Sopenharmony_ci	if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
190662306a36Sopenharmony_ci		start = 10;
190762306a36Sopenharmony_ci		*pr = false;
190862306a36Sopenharmony_ci	} else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
190962306a36Sopenharmony_ci		start = 8;
191062306a36Sopenharmony_ci	} else {
191162306a36Sopenharmony_ci		return;
191262306a36Sopenharmony_ci	}
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	/* remove the first part */
191562306a36Sopenharmony_ci	len = strlen(cra_driver_name) - start;
191662306a36Sopenharmony_ci	for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
191762306a36Sopenharmony_ci		if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
191862306a36Sopenharmony_ci			    len)) {
191962306a36Sopenharmony_ci			*coreref = i;
192062306a36Sopenharmony_ci			return;
192162306a36Sopenharmony_ci		}
192262306a36Sopenharmony_ci	}
192362306a36Sopenharmony_ci}
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_cistatic int drbg_kcapi_init(struct crypto_tfm *tfm)
192662306a36Sopenharmony_ci{
192762306a36Sopenharmony_ci	struct drbg_state *drbg = crypto_tfm_ctx(tfm);
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	mutex_init(&drbg->drbg_mutex);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	return 0;
193262306a36Sopenharmony_ci}
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_cistatic void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
193562306a36Sopenharmony_ci{
193662306a36Sopenharmony_ci	drbg_uninstantiate(crypto_tfm_ctx(tfm));
193762306a36Sopenharmony_ci}
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ci/*
194062306a36Sopenharmony_ci * Generate random numbers invoked by the kernel crypto API:
194162306a36Sopenharmony_ci * The API of the kernel crypto API is extended as follows:
194262306a36Sopenharmony_ci *
194362306a36Sopenharmony_ci * src is additional input supplied to the RNG.
194462306a36Sopenharmony_ci * slen is the length of src.
194562306a36Sopenharmony_ci * dst is the output buffer where random data is to be stored.
194662306a36Sopenharmony_ci * dlen is the length of dst.
194762306a36Sopenharmony_ci */
194862306a36Sopenharmony_cistatic int drbg_kcapi_random(struct crypto_rng *tfm,
194962306a36Sopenharmony_ci			     const u8 *src, unsigned int slen,
195062306a36Sopenharmony_ci			     u8 *dst, unsigned int dlen)
195162306a36Sopenharmony_ci{
195262306a36Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
195362306a36Sopenharmony_ci	struct drbg_string *addtl = NULL;
195462306a36Sopenharmony_ci	struct drbg_string string;
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ci	if (slen) {
195762306a36Sopenharmony_ci		/* linked list variable is now local to allow modification */
195862306a36Sopenharmony_ci		drbg_string_fill(&string, src, slen);
195962306a36Sopenharmony_ci		addtl = &string;
196062306a36Sopenharmony_ci	}
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	return drbg_generate_long(drbg, dst, dlen, addtl);
196362306a36Sopenharmony_ci}
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci/*
196662306a36Sopenharmony_ci * Seed the DRBG invoked by the kernel crypto API
196762306a36Sopenharmony_ci */
196862306a36Sopenharmony_cistatic int drbg_kcapi_seed(struct crypto_rng *tfm,
196962306a36Sopenharmony_ci			   const u8 *seed, unsigned int slen)
197062306a36Sopenharmony_ci{
197162306a36Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
197262306a36Sopenharmony_ci	struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
197362306a36Sopenharmony_ci	bool pr = false;
197462306a36Sopenharmony_ci	struct drbg_string string;
197562306a36Sopenharmony_ci	struct drbg_string *seed_string = NULL;
197662306a36Sopenharmony_ci	int coreref = 0;
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
197962306a36Sopenharmony_ci			      &pr);
198062306a36Sopenharmony_ci	if (0 < slen) {
198162306a36Sopenharmony_ci		drbg_string_fill(&string, seed, slen);
198262306a36Sopenharmony_ci		seed_string = &string;
198362306a36Sopenharmony_ci	}
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	return drbg_instantiate(drbg, seed_string, coreref, pr);
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci/***************************************************************
198962306a36Sopenharmony_ci * Kernel module: code to load the module
199062306a36Sopenharmony_ci ***************************************************************/
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_ci/*
199362306a36Sopenharmony_ci * Tests as defined in 11.3.2 in addition to the cipher tests: testing
199462306a36Sopenharmony_ci * of the error handling.
199562306a36Sopenharmony_ci *
199662306a36Sopenharmony_ci * Note: testing of failing seed source as defined in 11.3.2 is not applicable
199762306a36Sopenharmony_ci * as seed source of get_random_bytes does not fail.
199862306a36Sopenharmony_ci *
199962306a36Sopenharmony_ci * Note 2: There is no sensible way of testing the reseed counter
200062306a36Sopenharmony_ci * enforcement, so skip it.
200162306a36Sopenharmony_ci */
200262306a36Sopenharmony_cistatic inline int __init drbg_healthcheck_sanity(void)
200362306a36Sopenharmony_ci{
200462306a36Sopenharmony_ci	int len = 0;
200562306a36Sopenharmony_ci#define OUTBUFLEN 16
200662306a36Sopenharmony_ci	unsigned char buf[OUTBUFLEN];
200762306a36Sopenharmony_ci	struct drbg_state *drbg = NULL;
200862306a36Sopenharmony_ci	int ret;
200962306a36Sopenharmony_ci	int rc = -EFAULT;
201062306a36Sopenharmony_ci	bool pr = false;
201162306a36Sopenharmony_ci	int coreref = 0;
201262306a36Sopenharmony_ci	struct drbg_string addtl;
201362306a36Sopenharmony_ci	size_t max_addtllen, max_request_bytes;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	/* only perform test in FIPS mode */
201662306a36Sopenharmony_ci	if (!fips_enabled)
201762306a36Sopenharmony_ci		return 0;
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
202062306a36Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
202162306a36Sopenharmony_ci#elif defined CONFIG_CRYPTO_DRBG_HASH
202262306a36Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
202362306a36Sopenharmony_ci#else
202462306a36Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref, &pr);
202562306a36Sopenharmony_ci#endif
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
202862306a36Sopenharmony_ci	if (!drbg)
202962306a36Sopenharmony_ci		return -ENOMEM;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	mutex_init(&drbg->drbg_mutex);
203262306a36Sopenharmony_ci	drbg->core = &drbg_cores[coreref];
203362306a36Sopenharmony_ci	drbg->reseed_threshold = drbg_max_requests(drbg);
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	/*
203662306a36Sopenharmony_ci	 * if the following tests fail, it is likely that there is a buffer
203762306a36Sopenharmony_ci	 * overflow as buf is much smaller than the requested or provided
203862306a36Sopenharmony_ci	 * string lengths -- in case the error handling does not succeed
203962306a36Sopenharmony_ci	 * we may get an OOPS. And we want to get an OOPS as this is a
204062306a36Sopenharmony_ci	 * grave bug.
204162306a36Sopenharmony_ci	 */
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	max_addtllen = drbg_max_addtl(drbg);
204462306a36Sopenharmony_ci	max_request_bytes = drbg_max_request_bytes(drbg);
204562306a36Sopenharmony_ci	drbg_string_fill(&addtl, buf, max_addtllen + 1);
204662306a36Sopenharmony_ci	/* overflow addtllen with additonal info string */
204762306a36Sopenharmony_ci	len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
204862306a36Sopenharmony_ci	BUG_ON(0 < len);
204962306a36Sopenharmony_ci	/* overflow max_bits */
205062306a36Sopenharmony_ci	len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
205162306a36Sopenharmony_ci	BUG_ON(0 < len);
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci	/* overflow max addtllen with personalization string */
205462306a36Sopenharmony_ci	ret = drbg_seed(drbg, &addtl, false);
205562306a36Sopenharmony_ci	BUG_ON(0 == ret);
205662306a36Sopenharmony_ci	/* all tests passed */
205762306a36Sopenharmony_ci	rc = 0;
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	pr_devel("DRBG: Sanity tests for failure code paths successfully "
206062306a36Sopenharmony_ci		 "completed\n");
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci	kfree(drbg);
206362306a36Sopenharmony_ci	return rc;
206462306a36Sopenharmony_ci}
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_cistatic struct rng_alg drbg_algs[22];
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci/*
206962306a36Sopenharmony_ci * Fill the array drbg_algs used to register the different DRBGs
207062306a36Sopenharmony_ci * with the kernel crypto API. To fill the array, the information
207162306a36Sopenharmony_ci * from drbg_cores[] is used.
207262306a36Sopenharmony_ci */
207362306a36Sopenharmony_cistatic inline void __init drbg_fill_array(struct rng_alg *alg,
207462306a36Sopenharmony_ci					  const struct drbg_core *core, int pr)
207562306a36Sopenharmony_ci{
207662306a36Sopenharmony_ci	int pos = 0;
207762306a36Sopenharmony_ci	static int priority = 200;
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	memcpy(alg->base.cra_name, "stdrng", 6);
208062306a36Sopenharmony_ci	if (pr) {
208162306a36Sopenharmony_ci		memcpy(alg->base.cra_driver_name, "drbg_pr_", 8);
208262306a36Sopenharmony_ci		pos = 8;
208362306a36Sopenharmony_ci	} else {
208462306a36Sopenharmony_ci		memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10);
208562306a36Sopenharmony_ci		pos = 10;
208662306a36Sopenharmony_ci	}
208762306a36Sopenharmony_ci	memcpy(alg->base.cra_driver_name + pos, core->cra_name,
208862306a36Sopenharmony_ci	       strlen(core->cra_name));
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	alg->base.cra_priority = priority;
209162306a36Sopenharmony_ci	priority++;
209262306a36Sopenharmony_ci	/*
209362306a36Sopenharmony_ci	 * If FIPS mode enabled, the selected DRBG shall have the
209462306a36Sopenharmony_ci	 * highest cra_priority over other stdrng instances to ensure
209562306a36Sopenharmony_ci	 * it is selected.
209662306a36Sopenharmony_ci	 */
209762306a36Sopenharmony_ci	if (fips_enabled)
209862306a36Sopenharmony_ci		alg->base.cra_priority += 200;
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	alg->base.cra_ctxsize 	= sizeof(struct drbg_state);
210162306a36Sopenharmony_ci	alg->base.cra_module	= THIS_MODULE;
210262306a36Sopenharmony_ci	alg->base.cra_init	= drbg_kcapi_init;
210362306a36Sopenharmony_ci	alg->base.cra_exit	= drbg_kcapi_cleanup;
210462306a36Sopenharmony_ci	alg->generate		= drbg_kcapi_random;
210562306a36Sopenharmony_ci	alg->seed		= drbg_kcapi_seed;
210662306a36Sopenharmony_ci	alg->set_ent		= drbg_kcapi_set_entropy;
210762306a36Sopenharmony_ci	alg->seedsize		= 0;
210862306a36Sopenharmony_ci}
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_cistatic int __init drbg_init(void)
211162306a36Sopenharmony_ci{
211262306a36Sopenharmony_ci	unsigned int i = 0; /* pointer to drbg_algs */
211362306a36Sopenharmony_ci	unsigned int j = 0; /* pointer to drbg_cores */
211462306a36Sopenharmony_ci	int ret;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	ret = drbg_healthcheck_sanity();
211762306a36Sopenharmony_ci	if (ret)
211862306a36Sopenharmony_ci		return ret;
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
212162306a36Sopenharmony_ci		pr_info("DRBG: Cannot register all DRBG types"
212262306a36Sopenharmony_ci			"(slots needed: %zu, slots available: %zu)\n",
212362306a36Sopenharmony_ci			ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
212462306a36Sopenharmony_ci		return -EFAULT;
212562306a36Sopenharmony_ci	}
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_ci	/*
212862306a36Sopenharmony_ci	 * each DRBG definition can be used with PR and without PR, thus
212962306a36Sopenharmony_ci	 * we instantiate each DRBG in drbg_cores[] twice.
213062306a36Sopenharmony_ci	 *
213162306a36Sopenharmony_ci	 * As the order of placing them into the drbg_algs array matters
213262306a36Sopenharmony_ci	 * (the later DRBGs receive a higher cra_priority) we register the
213362306a36Sopenharmony_ci	 * prediction resistance DRBGs first as the should not be too
213462306a36Sopenharmony_ci	 * interesting.
213562306a36Sopenharmony_ci	 */
213662306a36Sopenharmony_ci	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
213762306a36Sopenharmony_ci		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
213862306a36Sopenharmony_ci	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
213962306a36Sopenharmony_ci		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
214062306a36Sopenharmony_ci	return crypto_register_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
214162306a36Sopenharmony_ci}
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_cistatic void __exit drbg_exit(void)
214462306a36Sopenharmony_ci{
214562306a36Sopenharmony_ci	crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
214662306a36Sopenharmony_ci}
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_cisubsys_initcall(drbg_init);
214962306a36Sopenharmony_cimodule_exit(drbg_exit);
215062306a36Sopenharmony_ci#ifndef CRYPTO_DRBG_HASH_STRING
215162306a36Sopenharmony_ci#define CRYPTO_DRBG_HASH_STRING ""
215262306a36Sopenharmony_ci#endif
215362306a36Sopenharmony_ci#ifndef CRYPTO_DRBG_HMAC_STRING
215462306a36Sopenharmony_ci#define CRYPTO_DRBG_HMAC_STRING ""
215562306a36Sopenharmony_ci#endif
215662306a36Sopenharmony_ci#ifndef CRYPTO_DRBG_CTR_STRING
215762306a36Sopenharmony_ci#define CRYPTO_DRBG_CTR_STRING ""
215862306a36Sopenharmony_ci#endif
215962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
216062306a36Sopenharmony_ciMODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
216162306a36Sopenharmony_ciMODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
216262306a36Sopenharmony_ci		   "using following cores: "
216362306a36Sopenharmony_ci		   CRYPTO_DRBG_HASH_STRING
216462306a36Sopenharmony_ci		   CRYPTO_DRBG_HMAC_STRING
216562306a36Sopenharmony_ci		   CRYPTO_DRBG_CTR_STRING);
216662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("stdrng");
216762306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_INTERNAL);
2168