18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * DRBG: Deterministic Random Bits Generator
38c2ecf20Sopenharmony_ci *       Based on NIST Recommended DRBG from NIST SP800-90A with the following
48c2ecf20Sopenharmony_ci *       properties:
58c2ecf20Sopenharmony_ci *		* CTR DRBG with DF with AES-128, AES-192, AES-256 cores
68c2ecf20Sopenharmony_ci *		* Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
78c2ecf20Sopenharmony_ci *		* HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
88c2ecf20Sopenharmony_ci *		* with and without prediction resistance
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Copyright Stephan Mueller <smueller@chronox.de>, 2014
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
138c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
148c2ecf20Sopenharmony_ci * are met:
158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
168c2ecf20Sopenharmony_ci *    notice, and the entire permission notice in its entirety,
178c2ecf20Sopenharmony_ci *    including the disclaimer of warranties.
188c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
198c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
208c2ecf20Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
218c2ecf20Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote
228c2ecf20Sopenharmony_ci *    products derived from this software without specific prior
238c2ecf20Sopenharmony_ci *    written permission.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of
268c2ecf20Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL are
278c2ecf20Sopenharmony_ci * required INSTEAD OF the above restrictions.  (This clause is
288c2ecf20Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and
298c2ecf20Sopenharmony_ci * the restrictions contained in a BSD-style copyright.)
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
328c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
338c2ecf20Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
348c2ecf20Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
358c2ecf20Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
368c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
378c2ecf20Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
388c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
398c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
408c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
418c2ecf20Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
428c2ecf20Sopenharmony_ci * DAMAGE.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci * DRBG Usage
458c2ecf20Sopenharmony_ci * ==========
468c2ecf20Sopenharmony_ci * The SP 800-90A DRBG allows the user to specify a personalization string
478c2ecf20Sopenharmony_ci * for initialization as well as an additional information string for each
488c2ecf20Sopenharmony_ci * random number request. The following code fragments show how a caller
498c2ecf20Sopenharmony_ci * uses the kernel crypto API to use the full functionality of the DRBG.
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * Usage without any additional data
528c2ecf20Sopenharmony_ci * ---------------------------------
538c2ecf20Sopenharmony_ci * struct crypto_rng *drng;
548c2ecf20Sopenharmony_ci * int err;
558c2ecf20Sopenharmony_ci * char data[DATALEN];
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
588c2ecf20Sopenharmony_ci * err = crypto_rng_get_bytes(drng, &data, DATALEN);
598c2ecf20Sopenharmony_ci * crypto_free_rng(drng);
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci *
628c2ecf20Sopenharmony_ci * Usage with personalization string during initialization
638c2ecf20Sopenharmony_ci * -------------------------------------------------------
648c2ecf20Sopenharmony_ci * struct crypto_rng *drng;
658c2ecf20Sopenharmony_ci * int err;
668c2ecf20Sopenharmony_ci * char data[DATALEN];
678c2ecf20Sopenharmony_ci * struct drbg_string pers;
688c2ecf20Sopenharmony_ci * char personalization[11] = "some-string";
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * drbg_string_fill(&pers, personalization, strlen(personalization));
718c2ecf20Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
728c2ecf20Sopenharmony_ci * // The reset completely re-initializes the DRBG with the provided
738c2ecf20Sopenharmony_ci * // personalization string
748c2ecf20Sopenharmony_ci * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
758c2ecf20Sopenharmony_ci * err = crypto_rng_get_bytes(drng, &data, DATALEN);
768c2ecf20Sopenharmony_ci * crypto_free_rng(drng);
778c2ecf20Sopenharmony_ci *
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * Usage with additional information string during random number request
808c2ecf20Sopenharmony_ci * ---------------------------------------------------------------------
818c2ecf20Sopenharmony_ci * struct crypto_rng *drng;
828c2ecf20Sopenharmony_ci * int err;
838c2ecf20Sopenharmony_ci * char data[DATALEN];
848c2ecf20Sopenharmony_ci * char addtl_string[11] = "some-string";
858c2ecf20Sopenharmony_ci * string drbg_string addtl;
868c2ecf20Sopenharmony_ci *
878c2ecf20Sopenharmony_ci * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
888c2ecf20Sopenharmony_ci * drng = crypto_alloc_rng(drng_name, 0, 0);
898c2ecf20Sopenharmony_ci * // The following call is a wrapper to crypto_rng_get_bytes() and returns
908c2ecf20Sopenharmony_ci * // the same error codes.
918c2ecf20Sopenharmony_ci * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
928c2ecf20Sopenharmony_ci * crypto_free_rng(drng);
938c2ecf20Sopenharmony_ci *
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * Usage with personalization and additional information strings
968c2ecf20Sopenharmony_ci * -------------------------------------------------------------
978c2ecf20Sopenharmony_ci * Just mix both scenarios above.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#include <crypto/drbg.h>
1018c2ecf20Sopenharmony_ci#include <linux/kernel.h>
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/***************************************************************
1048c2ecf20Sopenharmony_ci * Backend cipher definitions available to DRBG
1058c2ecf20Sopenharmony_ci ***************************************************************/
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/*
1088c2ecf20Sopenharmony_ci * The order of the DRBG definitions here matter: every DRBG is registered
1098c2ecf20Sopenharmony_ci * as stdrng. Each DRBG receives an increasing cra_priority values the later
1108c2ecf20Sopenharmony_ci * they are defined in this array (see drbg_fill_array).
1118c2ecf20Sopenharmony_ci *
1128c2ecf20Sopenharmony_ci * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and
1138c2ecf20Sopenharmony_ci * the SHA256 / AES 256 over other ciphers. Thus, the favored
1148c2ecf20Sopenharmony_ci * DRBGs are the latest entries in this array.
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_cistatic const struct drbg_core drbg_cores[] = {
1178c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
1188c2ecf20Sopenharmony_ci	{
1198c2ecf20Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH128,
1208c2ecf20Sopenharmony_ci		.statelen = 32, /* 256 bits as defined in 10.2.1 */
1218c2ecf20Sopenharmony_ci		.blocklen_bytes = 16,
1228c2ecf20Sopenharmony_ci		.cra_name = "ctr_aes128",
1238c2ecf20Sopenharmony_ci		.backend_cra_name = "aes",
1248c2ecf20Sopenharmony_ci	}, {
1258c2ecf20Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH192,
1268c2ecf20Sopenharmony_ci		.statelen = 40, /* 320 bits as defined in 10.2.1 */
1278c2ecf20Sopenharmony_ci		.blocklen_bytes = 16,
1288c2ecf20Sopenharmony_ci		.cra_name = "ctr_aes192",
1298c2ecf20Sopenharmony_ci		.backend_cra_name = "aes",
1308c2ecf20Sopenharmony_ci	}, {
1318c2ecf20Sopenharmony_ci		.flags = DRBG_CTR | DRBG_STRENGTH256,
1328c2ecf20Sopenharmony_ci		.statelen = 48, /* 384 bits as defined in 10.2.1 */
1338c2ecf20Sopenharmony_ci		.blocklen_bytes = 16,
1348c2ecf20Sopenharmony_ci		.cra_name = "ctr_aes256",
1358c2ecf20Sopenharmony_ci		.backend_cra_name = "aes",
1368c2ecf20Sopenharmony_ci	},
1378c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
1388c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
1398c2ecf20Sopenharmony_ci	{
1408c2ecf20Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH128,
1418c2ecf20Sopenharmony_ci		.statelen = 55, /* 440 bits */
1428c2ecf20Sopenharmony_ci		.blocklen_bytes = 20,
1438c2ecf20Sopenharmony_ci		.cra_name = "sha1",
1448c2ecf20Sopenharmony_ci		.backend_cra_name = "sha1",
1458c2ecf20Sopenharmony_ci	}, {
1468c2ecf20Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
1478c2ecf20Sopenharmony_ci		.statelen = 111, /* 888 bits */
1488c2ecf20Sopenharmony_ci		.blocklen_bytes = 48,
1498c2ecf20Sopenharmony_ci		.cra_name = "sha384",
1508c2ecf20Sopenharmony_ci		.backend_cra_name = "sha384",
1518c2ecf20Sopenharmony_ci	}, {
1528c2ecf20Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
1538c2ecf20Sopenharmony_ci		.statelen = 111, /* 888 bits */
1548c2ecf20Sopenharmony_ci		.blocklen_bytes = 64,
1558c2ecf20Sopenharmony_ci		.cra_name = "sha512",
1568c2ecf20Sopenharmony_ci		.backend_cra_name = "sha512",
1578c2ecf20Sopenharmony_ci	}, {
1588c2ecf20Sopenharmony_ci		.flags = DRBG_HASH | DRBG_STRENGTH256,
1598c2ecf20Sopenharmony_ci		.statelen = 55, /* 440 bits */
1608c2ecf20Sopenharmony_ci		.blocklen_bytes = 32,
1618c2ecf20Sopenharmony_ci		.cra_name = "sha256",
1628c2ecf20Sopenharmony_ci		.backend_cra_name = "sha256",
1638c2ecf20Sopenharmony_ci	},
1648c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
1658c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
1668c2ecf20Sopenharmony_ci	{
1678c2ecf20Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH128,
1688c2ecf20Sopenharmony_ci		.statelen = 20, /* block length of cipher */
1698c2ecf20Sopenharmony_ci		.blocklen_bytes = 20,
1708c2ecf20Sopenharmony_ci		.cra_name = "hmac_sha1",
1718c2ecf20Sopenharmony_ci		.backend_cra_name = "hmac(sha1)",
1728c2ecf20Sopenharmony_ci	}, {
1738c2ecf20Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
1748c2ecf20Sopenharmony_ci		.statelen = 48, /* block length of cipher */
1758c2ecf20Sopenharmony_ci		.blocklen_bytes = 48,
1768c2ecf20Sopenharmony_ci		.cra_name = "hmac_sha384",
1778c2ecf20Sopenharmony_ci		.backend_cra_name = "hmac(sha384)",
1788c2ecf20Sopenharmony_ci	}, {
1798c2ecf20Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
1808c2ecf20Sopenharmony_ci		.statelen = 64, /* block length of cipher */
1818c2ecf20Sopenharmony_ci		.blocklen_bytes = 64,
1828c2ecf20Sopenharmony_ci		.cra_name = "hmac_sha512",
1838c2ecf20Sopenharmony_ci		.backend_cra_name = "hmac(sha512)",
1848c2ecf20Sopenharmony_ci	}, {
1858c2ecf20Sopenharmony_ci		.flags = DRBG_HMAC | DRBG_STRENGTH256,
1868c2ecf20Sopenharmony_ci		.statelen = 32, /* block length of cipher */
1878c2ecf20Sopenharmony_ci		.blocklen_bytes = 32,
1888c2ecf20Sopenharmony_ci		.cra_name = "hmac_sha256",
1898c2ecf20Sopenharmony_ci		.backend_cra_name = "hmac(sha256)",
1908c2ecf20Sopenharmony_ci	},
1918c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
1928c2ecf20Sopenharmony_ci};
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic int drbg_uninstantiate(struct drbg_state *drbg);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci/******************************************************************
1978c2ecf20Sopenharmony_ci * Generic helper functions
1988c2ecf20Sopenharmony_ci ******************************************************************/
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci/*
2018c2ecf20Sopenharmony_ci * Return strength of DRBG according to SP800-90A section 8.4
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * @flags DRBG flags reference
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci * Return: normalized strength in *bytes* value or 32 as default
2068c2ecf20Sopenharmony_ci *	   to counter programming errors
2078c2ecf20Sopenharmony_ci */
2088c2ecf20Sopenharmony_cistatic inline unsigned short drbg_sec_strength(drbg_flag_t flags)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	switch (flags & DRBG_STRENGTH_MASK) {
2118c2ecf20Sopenharmony_ci	case DRBG_STRENGTH128:
2128c2ecf20Sopenharmony_ci		return 16;
2138c2ecf20Sopenharmony_ci	case DRBG_STRENGTH192:
2148c2ecf20Sopenharmony_ci		return 24;
2158c2ecf20Sopenharmony_ci	case DRBG_STRENGTH256:
2168c2ecf20Sopenharmony_ci		return 32;
2178c2ecf20Sopenharmony_ci	default:
2188c2ecf20Sopenharmony_ci		return 32;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/*
2238c2ecf20Sopenharmony_ci * FIPS 140-2 continuous self test for the noise source
2248c2ecf20Sopenharmony_ci * The test is performed on the noise source input data. Thus, the function
2258c2ecf20Sopenharmony_ci * implicitly knows the size of the buffer to be equal to the security
2268c2ecf20Sopenharmony_ci * strength.
2278c2ecf20Sopenharmony_ci *
2288c2ecf20Sopenharmony_ci * Note, this function disregards the nonce trailing the entropy data during
2298c2ecf20Sopenharmony_ci * initial seeding.
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * drbg->drbg_mutex must have been taken.
2328c2ecf20Sopenharmony_ci *
2338c2ecf20Sopenharmony_ci * @drbg DRBG handle
2348c2ecf20Sopenharmony_ci * @entropy buffer of seed data to be checked
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * return:
2378c2ecf20Sopenharmony_ci *	0 on success
2388c2ecf20Sopenharmony_ci *	-EAGAIN on when the CTRNG is not yet primed
2398c2ecf20Sopenharmony_ci *	< 0 on error
2408c2ecf20Sopenharmony_ci */
2418c2ecf20Sopenharmony_cistatic int drbg_fips_continuous_test(struct drbg_state *drbg,
2428c2ecf20Sopenharmony_ci				     const unsigned char *entropy)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
2458c2ecf20Sopenharmony_ci	int ret = 0;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (!IS_ENABLED(CONFIG_CRYPTO_FIPS))
2488c2ecf20Sopenharmony_ci		return 0;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* skip test if we test the overall system */
2518c2ecf20Sopenharmony_ci	if (list_empty(&drbg->test_data.list))
2528c2ecf20Sopenharmony_ci		return 0;
2538c2ecf20Sopenharmony_ci	/* only perform test in FIPS mode */
2548c2ecf20Sopenharmony_ci	if (!fips_enabled)
2558c2ecf20Sopenharmony_ci		return 0;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	if (!drbg->fips_primed) {
2588c2ecf20Sopenharmony_ci		/* Priming of FIPS test */
2598c2ecf20Sopenharmony_ci		memcpy(drbg->prev, entropy, entropylen);
2608c2ecf20Sopenharmony_ci		drbg->fips_primed = true;
2618c2ecf20Sopenharmony_ci		/* priming: another round is needed */
2628c2ecf20Sopenharmony_ci		return -EAGAIN;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci	ret = memcmp(drbg->prev, entropy, entropylen);
2658c2ecf20Sopenharmony_ci	if (!ret)
2668c2ecf20Sopenharmony_ci		panic("DRBG continuous self test failed\n");
2678c2ecf20Sopenharmony_ci	memcpy(drbg->prev, entropy, entropylen);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	/* the test shall pass when the two values are not equal */
2708c2ecf20Sopenharmony_ci	return 0;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci/*
2748c2ecf20Sopenharmony_ci * Convert an integer into a byte representation of this integer.
2758c2ecf20Sopenharmony_ci * The byte representation is big-endian
2768c2ecf20Sopenharmony_ci *
2778c2ecf20Sopenharmony_ci * @val value to be converted
2788c2ecf20Sopenharmony_ci * @buf buffer holding the converted integer -- caller must ensure that
2798c2ecf20Sopenharmony_ci *      buffer size is at least 32 bit
2808c2ecf20Sopenharmony_ci */
2818c2ecf20Sopenharmony_ci#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
2828c2ecf20Sopenharmony_cistatic inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	struct s {
2858c2ecf20Sopenharmony_ci		__be32 conv;
2868c2ecf20Sopenharmony_ci	};
2878c2ecf20Sopenharmony_ci	struct s *conversion = (struct s *) buf;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	conversion->conv = cpu_to_be32(val);
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci/******************************************************************
2948c2ecf20Sopenharmony_ci * CTR DRBG callback functions
2958c2ecf20Sopenharmony_ci ******************************************************************/
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
2988c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_CTR_STRING "CTR "
2998c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes256");
3008c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes256");
3018c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes192");
3028c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes192");
3038c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128");
3048c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128");
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic void drbg_kcapi_symsetkey(struct drbg_state *drbg,
3078c2ecf20Sopenharmony_ci				 const unsigned char *key);
3088c2ecf20Sopenharmony_cistatic int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
3098c2ecf20Sopenharmony_ci			  const struct drbg_string *in);
3108c2ecf20Sopenharmony_cistatic int drbg_init_sym_kernel(struct drbg_state *drbg);
3118c2ecf20Sopenharmony_cistatic int drbg_fini_sym_kernel(struct drbg_state *drbg);
3128c2ecf20Sopenharmony_cistatic int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
3138c2ecf20Sopenharmony_ci			      u8 *inbuf, u32 inbuflen,
3148c2ecf20Sopenharmony_ci			      u8 *outbuf, u32 outlen);
3158c2ecf20Sopenharmony_ci#define DRBG_OUTSCRATCHLEN 256
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/* BCC function for CTR DRBG as defined in 10.4.3 */
3188c2ecf20Sopenharmony_cistatic int drbg_ctr_bcc(struct drbg_state *drbg,
3198c2ecf20Sopenharmony_ci			unsigned char *out, const unsigned char *key,
3208c2ecf20Sopenharmony_ci			struct list_head *in)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	int ret = 0;
3238c2ecf20Sopenharmony_ci	struct drbg_string *curr = NULL;
3248c2ecf20Sopenharmony_ci	struct drbg_string data;
3258c2ecf20Sopenharmony_ci	short cnt = 0;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	drbg_string_fill(&data, out, drbg_blocklen(drbg));
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* 10.4.3 step 2 / 4 */
3308c2ecf20Sopenharmony_ci	drbg_kcapi_symsetkey(drbg, key);
3318c2ecf20Sopenharmony_ci	list_for_each_entry(curr, in, list) {
3328c2ecf20Sopenharmony_ci		const unsigned char *pos = curr->buf;
3338c2ecf20Sopenharmony_ci		size_t len = curr->len;
3348c2ecf20Sopenharmony_ci		/* 10.4.3 step 4.1 */
3358c2ecf20Sopenharmony_ci		while (len) {
3368c2ecf20Sopenharmony_ci			/* 10.4.3 step 4.2 */
3378c2ecf20Sopenharmony_ci			if (drbg_blocklen(drbg) == cnt) {
3388c2ecf20Sopenharmony_ci				cnt = 0;
3398c2ecf20Sopenharmony_ci				ret = drbg_kcapi_sym(drbg, out, &data);
3408c2ecf20Sopenharmony_ci				if (ret)
3418c2ecf20Sopenharmony_ci					return ret;
3428c2ecf20Sopenharmony_ci			}
3438c2ecf20Sopenharmony_ci			out[cnt] ^= *pos;
3448c2ecf20Sopenharmony_ci			pos++;
3458c2ecf20Sopenharmony_ci			cnt++;
3468c2ecf20Sopenharmony_ci			len--;
3478c2ecf20Sopenharmony_ci		}
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci	/* 10.4.3 step 4.2 for last block */
3508c2ecf20Sopenharmony_ci	if (cnt)
3518c2ecf20Sopenharmony_ci		ret = drbg_kcapi_sym(drbg, out, &data);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return ret;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci/*
3578c2ecf20Sopenharmony_ci * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
3588c2ecf20Sopenharmony_ci * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
3598c2ecf20Sopenharmony_ci * the scratchpad is used as follows:
3608c2ecf20Sopenharmony_ci * drbg_ctr_update:
3618c2ecf20Sopenharmony_ci *	temp
3628c2ecf20Sopenharmony_ci *		start: drbg->scratchpad
3638c2ecf20Sopenharmony_ci *		length: drbg_statelen(drbg) + drbg_blocklen(drbg)
3648c2ecf20Sopenharmony_ci *			note: the cipher writing into this variable works
3658c2ecf20Sopenharmony_ci *			blocklen-wise. Now, when the statelen is not a multiple
3668c2ecf20Sopenharmony_ci *			of blocklen, the generateion loop below "spills over"
3678c2ecf20Sopenharmony_ci *			by at most blocklen. Thus, we need to give sufficient
3688c2ecf20Sopenharmony_ci *			memory.
3698c2ecf20Sopenharmony_ci *	df_data
3708c2ecf20Sopenharmony_ci *		start: drbg->scratchpad +
3718c2ecf20Sopenharmony_ci *				drbg_statelen(drbg) + drbg_blocklen(drbg)
3728c2ecf20Sopenharmony_ci *		length: drbg_statelen(drbg)
3738c2ecf20Sopenharmony_ci *
3748c2ecf20Sopenharmony_ci * drbg_ctr_df:
3758c2ecf20Sopenharmony_ci *	pad
3768c2ecf20Sopenharmony_ci *		start: df_data + drbg_statelen(drbg)
3778c2ecf20Sopenharmony_ci *		length: drbg_blocklen(drbg)
3788c2ecf20Sopenharmony_ci *	iv
3798c2ecf20Sopenharmony_ci *		start: pad + drbg_blocklen(drbg)
3808c2ecf20Sopenharmony_ci *		length: drbg_blocklen(drbg)
3818c2ecf20Sopenharmony_ci *	temp
3828c2ecf20Sopenharmony_ci *		start: iv + drbg_blocklen(drbg)
3838c2ecf20Sopenharmony_ci *		length: drbg_satelen(drbg) + drbg_blocklen(drbg)
3848c2ecf20Sopenharmony_ci *			note: temp is the buffer that the BCC function operates
3858c2ecf20Sopenharmony_ci *			on. BCC operates blockwise. drbg_statelen(drbg)
3868c2ecf20Sopenharmony_ci *			is sufficient when the DRBG state length is a multiple
3878c2ecf20Sopenharmony_ci *			of the block size. For AES192 (and maybe other ciphers)
3888c2ecf20Sopenharmony_ci *			this is not correct and the length for temp is
3898c2ecf20Sopenharmony_ci *			insufficient (yes, that also means for such ciphers,
3908c2ecf20Sopenharmony_ci *			the final output of all BCC rounds are truncated).
3918c2ecf20Sopenharmony_ci *			Therefore, add drbg_blocklen(drbg) to cover all
3928c2ecf20Sopenharmony_ci *			possibilities.
3938c2ecf20Sopenharmony_ci */
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci/* Derivation Function for CTR DRBG as defined in 10.4.2 */
3968c2ecf20Sopenharmony_cistatic int drbg_ctr_df(struct drbg_state *drbg,
3978c2ecf20Sopenharmony_ci		       unsigned char *df_data, size_t bytes_to_return,
3988c2ecf20Sopenharmony_ci		       struct list_head *seedlist)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	int ret = -EFAULT;
4018c2ecf20Sopenharmony_ci	unsigned char L_N[8];
4028c2ecf20Sopenharmony_ci	/* S3 is input */
4038c2ecf20Sopenharmony_ci	struct drbg_string S1, S2, S4, cipherin;
4048c2ecf20Sopenharmony_ci	LIST_HEAD(bcc_list);
4058c2ecf20Sopenharmony_ci	unsigned char *pad = df_data + drbg_statelen(drbg);
4068c2ecf20Sopenharmony_ci	unsigned char *iv = pad + drbg_blocklen(drbg);
4078c2ecf20Sopenharmony_ci	unsigned char *temp = iv + drbg_blocklen(drbg);
4088c2ecf20Sopenharmony_ci	size_t padlen = 0;
4098c2ecf20Sopenharmony_ci	unsigned int templen = 0;
4108c2ecf20Sopenharmony_ci	/* 10.4.2 step 7 */
4118c2ecf20Sopenharmony_ci	unsigned int i = 0;
4128c2ecf20Sopenharmony_ci	/* 10.4.2 step 8 */
4138c2ecf20Sopenharmony_ci	const unsigned char *K = (unsigned char *)
4148c2ecf20Sopenharmony_ci			   "\x00\x01\x02\x03\x04\x05\x06\x07"
4158c2ecf20Sopenharmony_ci			   "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
4168c2ecf20Sopenharmony_ci			   "\x10\x11\x12\x13\x14\x15\x16\x17"
4178c2ecf20Sopenharmony_ci			   "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
4188c2ecf20Sopenharmony_ci	unsigned char *X;
4198c2ecf20Sopenharmony_ci	size_t generated_len = 0;
4208c2ecf20Sopenharmony_ci	size_t inputlen = 0;
4218c2ecf20Sopenharmony_ci	struct drbg_string *seed = NULL;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	memset(pad, 0, drbg_blocklen(drbg));
4248c2ecf20Sopenharmony_ci	memset(iv, 0, drbg_blocklen(drbg));
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/* 10.4.2 step 1 is implicit as we work byte-wise */
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* 10.4.2 step 2 */
4298c2ecf20Sopenharmony_ci	if ((512/8) < bytes_to_return)
4308c2ecf20Sopenharmony_ci		return -EINVAL;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	/* 10.4.2 step 2 -- calculate the entire length of all input data */
4338c2ecf20Sopenharmony_ci	list_for_each_entry(seed, seedlist, list)
4348c2ecf20Sopenharmony_ci		inputlen += seed->len;
4358c2ecf20Sopenharmony_ci	drbg_cpu_to_be32(inputlen, &L_N[0]);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	/* 10.4.2 step 3 */
4388c2ecf20Sopenharmony_ci	drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
4418c2ecf20Sopenharmony_ci	padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
4428c2ecf20Sopenharmony_ci	/* wrap the padlen appropriately */
4438c2ecf20Sopenharmony_ci	if (padlen)
4448c2ecf20Sopenharmony_ci		padlen = drbg_blocklen(drbg) - padlen;
4458c2ecf20Sopenharmony_ci	/*
4468c2ecf20Sopenharmony_ci	 * pad / padlen contains the 0x80 byte and the following zero bytes.
4478c2ecf20Sopenharmony_ci	 * As the calculated padlen value only covers the number of zero
4488c2ecf20Sopenharmony_ci	 * bytes, this value has to be incremented by one for the 0x80 byte.
4498c2ecf20Sopenharmony_ci	 */
4508c2ecf20Sopenharmony_ci	padlen++;
4518c2ecf20Sopenharmony_ci	pad[0] = 0x80;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	/* 10.4.2 step 4 -- first fill the linked list and then order it */
4548c2ecf20Sopenharmony_ci	drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
4558c2ecf20Sopenharmony_ci	list_add_tail(&S1.list, &bcc_list);
4568c2ecf20Sopenharmony_ci	drbg_string_fill(&S2, L_N, sizeof(L_N));
4578c2ecf20Sopenharmony_ci	list_add_tail(&S2.list, &bcc_list);
4588c2ecf20Sopenharmony_ci	list_splice_tail(seedlist, &bcc_list);
4598c2ecf20Sopenharmony_ci	drbg_string_fill(&S4, pad, padlen);
4608c2ecf20Sopenharmony_ci	list_add_tail(&S4.list, &bcc_list);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/* 10.4.2 step 9 */
4638c2ecf20Sopenharmony_ci	while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
4648c2ecf20Sopenharmony_ci		/*
4658c2ecf20Sopenharmony_ci		 * 10.4.2 step 9.1 - the padding is implicit as the buffer
4668c2ecf20Sopenharmony_ci		 * holds zeros after allocation -- even the increment of i
4678c2ecf20Sopenharmony_ci		 * is irrelevant as the increment remains within length of i
4688c2ecf20Sopenharmony_ci		 */
4698c2ecf20Sopenharmony_ci		drbg_cpu_to_be32(i, iv);
4708c2ecf20Sopenharmony_ci		/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
4718c2ecf20Sopenharmony_ci		ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
4728c2ecf20Sopenharmony_ci		if (ret)
4738c2ecf20Sopenharmony_ci			goto out;
4748c2ecf20Sopenharmony_ci		/* 10.4.2 step 9.3 */
4758c2ecf20Sopenharmony_ci		i++;
4768c2ecf20Sopenharmony_ci		templen += drbg_blocklen(drbg);
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	/* 10.4.2 step 11 */
4808c2ecf20Sopenharmony_ci	X = temp + (drbg_keylen(drbg));
4818c2ecf20Sopenharmony_ci	drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/* 10.4.2 step 12: overwriting of outval is implemented in next step */
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	/* 10.4.2 step 13 */
4868c2ecf20Sopenharmony_ci	drbg_kcapi_symsetkey(drbg, temp);
4878c2ecf20Sopenharmony_ci	while (generated_len < bytes_to_return) {
4888c2ecf20Sopenharmony_ci		short blocklen = 0;
4898c2ecf20Sopenharmony_ci		/*
4908c2ecf20Sopenharmony_ci		 * 10.4.2 step 13.1: the truncation of the key length is
4918c2ecf20Sopenharmony_ci		 * implicit as the key is only drbg_blocklen in size based on
4928c2ecf20Sopenharmony_ci		 * the implementation of the cipher function callback
4938c2ecf20Sopenharmony_ci		 */
4948c2ecf20Sopenharmony_ci		ret = drbg_kcapi_sym(drbg, X, &cipherin);
4958c2ecf20Sopenharmony_ci		if (ret)
4968c2ecf20Sopenharmony_ci			goto out;
4978c2ecf20Sopenharmony_ci		blocklen = (drbg_blocklen(drbg) <
4988c2ecf20Sopenharmony_ci				(bytes_to_return - generated_len)) ?
4998c2ecf20Sopenharmony_ci			    drbg_blocklen(drbg) :
5008c2ecf20Sopenharmony_ci				(bytes_to_return - generated_len);
5018c2ecf20Sopenharmony_ci		/* 10.4.2 step 13.2 and 14 */
5028c2ecf20Sopenharmony_ci		memcpy(df_data + generated_len, X, blocklen);
5038c2ecf20Sopenharmony_ci		generated_len += blocklen;
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	ret = 0;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ciout:
5098c2ecf20Sopenharmony_ci	memset(iv, 0, drbg_blocklen(drbg));
5108c2ecf20Sopenharmony_ci	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
5118c2ecf20Sopenharmony_ci	memset(pad, 0, drbg_blocklen(drbg));
5128c2ecf20Sopenharmony_ci	return ret;
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci/*
5168c2ecf20Sopenharmony_ci * update function of CTR DRBG as defined in 10.2.1.2
5178c2ecf20Sopenharmony_ci *
5188c2ecf20Sopenharmony_ci * The reseed variable has an enhanced meaning compared to the update
5198c2ecf20Sopenharmony_ci * functions of the other DRBGs as follows:
5208c2ecf20Sopenharmony_ci * 0 => initial seed from initialization
5218c2ecf20Sopenharmony_ci * 1 => reseed via drbg_seed
5228c2ecf20Sopenharmony_ci * 2 => first invocation from drbg_ctr_update when addtl is present. In
5238c2ecf20Sopenharmony_ci *      this case, the df_data scratchpad is not deleted so that it is
5248c2ecf20Sopenharmony_ci *      available for another calls to prevent calling the DF function
5258c2ecf20Sopenharmony_ci *      again.
5268c2ecf20Sopenharmony_ci * 3 => second invocation from drbg_ctr_update. When the update function
5278c2ecf20Sopenharmony_ci *      was called with addtl, the df_data memory already contains the
5288c2ecf20Sopenharmony_ci *      DFed addtl information and we do not need to call DF again.
5298c2ecf20Sopenharmony_ci */
5308c2ecf20Sopenharmony_cistatic int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
5318c2ecf20Sopenharmony_ci			   int reseed)
5328c2ecf20Sopenharmony_ci{
5338c2ecf20Sopenharmony_ci	int ret = -EFAULT;
5348c2ecf20Sopenharmony_ci	/* 10.2.1.2 step 1 */
5358c2ecf20Sopenharmony_ci	unsigned char *temp = drbg->scratchpad;
5368c2ecf20Sopenharmony_ci	unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
5378c2ecf20Sopenharmony_ci				 drbg_blocklen(drbg);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	if (3 > reseed)
5408c2ecf20Sopenharmony_ci		memset(df_data, 0, drbg_statelen(drbg));
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	if (!reseed) {
5438c2ecf20Sopenharmony_ci		/*
5448c2ecf20Sopenharmony_ci		 * The DRBG uses the CTR mode of the underlying AES cipher. The
5458c2ecf20Sopenharmony_ci		 * CTR mode increments the counter value after the AES operation
5468c2ecf20Sopenharmony_ci		 * but SP800-90A requires that the counter is incremented before
5478c2ecf20Sopenharmony_ci		 * the AES operation. Hence, we increment it at the time we set
5488c2ecf20Sopenharmony_ci		 * it by one.
5498c2ecf20Sopenharmony_ci		 */
5508c2ecf20Sopenharmony_ci		crypto_inc(drbg->V, drbg_blocklen(drbg));
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci		ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
5538c2ecf20Sopenharmony_ci					     drbg_keylen(drbg));
5548c2ecf20Sopenharmony_ci		if (ret)
5558c2ecf20Sopenharmony_ci			goto out;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	/* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
5598c2ecf20Sopenharmony_ci	if (seed) {
5608c2ecf20Sopenharmony_ci		ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
5618c2ecf20Sopenharmony_ci		if (ret)
5628c2ecf20Sopenharmony_ci			goto out;
5638c2ecf20Sopenharmony_ci	}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg),
5668c2ecf20Sopenharmony_ci				 temp, drbg_statelen(drbg));
5678c2ecf20Sopenharmony_ci	if (ret)
5688c2ecf20Sopenharmony_ci		return ret;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	/* 10.2.1.2 step 5 */
5718c2ecf20Sopenharmony_ci	ret = crypto_skcipher_setkey(drbg->ctr_handle, temp,
5728c2ecf20Sopenharmony_ci				     drbg_keylen(drbg));
5738c2ecf20Sopenharmony_ci	if (ret)
5748c2ecf20Sopenharmony_ci		goto out;
5758c2ecf20Sopenharmony_ci	/* 10.2.1.2 step 6 */
5768c2ecf20Sopenharmony_ci	memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
5778c2ecf20Sopenharmony_ci	/* See above: increment counter by one to compensate timing of CTR op */
5788c2ecf20Sopenharmony_ci	crypto_inc(drbg->V, drbg_blocklen(drbg));
5798c2ecf20Sopenharmony_ci	ret = 0;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ciout:
5828c2ecf20Sopenharmony_ci	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
5838c2ecf20Sopenharmony_ci	if (2 != reseed)
5848c2ecf20Sopenharmony_ci		memset(df_data, 0, drbg_statelen(drbg));
5858c2ecf20Sopenharmony_ci	return ret;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci/*
5898c2ecf20Sopenharmony_ci * scratchpad use: drbg_ctr_update is called independently from
5908c2ecf20Sopenharmony_ci * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
5918c2ecf20Sopenharmony_ci */
5928c2ecf20Sopenharmony_ci/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
5938c2ecf20Sopenharmony_cistatic int drbg_ctr_generate(struct drbg_state *drbg,
5948c2ecf20Sopenharmony_ci			     unsigned char *buf, unsigned int buflen,
5958c2ecf20Sopenharmony_ci			     struct list_head *addtl)
5968c2ecf20Sopenharmony_ci{
5978c2ecf20Sopenharmony_ci	int ret;
5988c2ecf20Sopenharmony_ci	int len = min_t(int, buflen, INT_MAX);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	/* 10.2.1.5.2 step 2 */
6018c2ecf20Sopenharmony_ci	if (addtl && !list_empty(addtl)) {
6028c2ecf20Sopenharmony_ci		ret = drbg_ctr_update(drbg, addtl, 2);
6038c2ecf20Sopenharmony_ci		if (ret)
6048c2ecf20Sopenharmony_ci			return 0;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	/* 10.2.1.5.2 step 4.1 */
6088c2ecf20Sopenharmony_ci	ret = drbg_kcapi_sym_ctr(drbg, NULL, 0, buf, len);
6098c2ecf20Sopenharmony_ci	if (ret)
6108c2ecf20Sopenharmony_ci		return ret;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* 10.2.1.5.2 step 6 */
6138c2ecf20Sopenharmony_ci	ret = drbg_ctr_update(drbg, NULL, 3);
6148c2ecf20Sopenharmony_ci	if (ret)
6158c2ecf20Sopenharmony_ci		len = ret;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	return len;
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_cistatic const struct drbg_state_ops drbg_ctr_ops = {
6218c2ecf20Sopenharmony_ci	.update		= drbg_ctr_update,
6228c2ecf20Sopenharmony_ci	.generate	= drbg_ctr_generate,
6238c2ecf20Sopenharmony_ci	.crypto_init	= drbg_init_sym_kernel,
6248c2ecf20Sopenharmony_ci	.crypto_fini	= drbg_fini_sym_kernel,
6258c2ecf20Sopenharmony_ci};
6268c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci/******************************************************************
6298c2ecf20Sopenharmony_ci * HMAC DRBG callback functions
6308c2ecf20Sopenharmony_ci ******************************************************************/
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
6338c2ecf20Sopenharmony_cistatic int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
6348c2ecf20Sopenharmony_ci			   const struct list_head *in);
6358c2ecf20Sopenharmony_cistatic void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
6368c2ecf20Sopenharmony_ci				  const unsigned char *key);
6378c2ecf20Sopenharmony_cistatic int drbg_init_hash_kernel(struct drbg_state *drbg);
6388c2ecf20Sopenharmony_cistatic int drbg_fini_hash_kernel(struct drbg_state *drbg);
6398c2ecf20Sopenharmony_ci#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
6428c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_HMAC_STRING "HMAC "
6438c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
6448c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
6458c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384");
6468c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha384");
6478c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha256");
6488c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha256");
6498c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha1");
6508c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha1");
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci/* update function of HMAC DRBG as defined in 10.1.2.2 */
6538c2ecf20Sopenharmony_cistatic int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
6548c2ecf20Sopenharmony_ci			    int reseed)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	int ret = -EFAULT;
6578c2ecf20Sopenharmony_ci	int i = 0;
6588c2ecf20Sopenharmony_ci	struct drbg_string seed1, seed2, vdata;
6598c2ecf20Sopenharmony_ci	LIST_HEAD(seedlist);
6608c2ecf20Sopenharmony_ci	LIST_HEAD(vdatalist);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	if (!reseed) {
6638c2ecf20Sopenharmony_ci		/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
6648c2ecf20Sopenharmony_ci		memset(drbg->V, 1, drbg_statelen(drbg));
6658c2ecf20Sopenharmony_ci		drbg_kcapi_hmacsetkey(drbg, drbg->C);
6668c2ecf20Sopenharmony_ci	}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
6698c2ecf20Sopenharmony_ci	list_add_tail(&seed1.list, &seedlist);
6708c2ecf20Sopenharmony_ci	/* buffer of seed2 will be filled in for loop below with one byte */
6718c2ecf20Sopenharmony_ci	drbg_string_fill(&seed2, NULL, 1);
6728c2ecf20Sopenharmony_ci	list_add_tail(&seed2.list, &seedlist);
6738c2ecf20Sopenharmony_ci	/* input data of seed is allowed to be NULL at this point */
6748c2ecf20Sopenharmony_ci	if (seed)
6758c2ecf20Sopenharmony_ci		list_splice_tail(seed, &seedlist);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
6788c2ecf20Sopenharmony_ci	list_add_tail(&vdata.list, &vdatalist);
6798c2ecf20Sopenharmony_ci	for (i = 2; 0 < i; i--) {
6808c2ecf20Sopenharmony_ci		/* first round uses 0x0, second 0x1 */
6818c2ecf20Sopenharmony_ci		unsigned char prefix = DRBG_PREFIX0;
6828c2ecf20Sopenharmony_ci		if (1 == i)
6838c2ecf20Sopenharmony_ci			prefix = DRBG_PREFIX1;
6848c2ecf20Sopenharmony_ci		/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
6858c2ecf20Sopenharmony_ci		seed2.buf = &prefix;
6868c2ecf20Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
6878c2ecf20Sopenharmony_ci		if (ret)
6888c2ecf20Sopenharmony_ci			return ret;
6898c2ecf20Sopenharmony_ci		drbg_kcapi_hmacsetkey(drbg, drbg->C);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci		/* 10.1.2.2 step 2 and 5 -- HMAC for V */
6928c2ecf20Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
6938c2ecf20Sopenharmony_ci		if (ret)
6948c2ecf20Sopenharmony_ci			return ret;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		/* 10.1.2.2 step 3 */
6978c2ecf20Sopenharmony_ci		if (!seed)
6988c2ecf20Sopenharmony_ci			return ret;
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	return 0;
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci/* generate function of HMAC DRBG as defined in 10.1.2.5 */
7058c2ecf20Sopenharmony_cistatic int drbg_hmac_generate(struct drbg_state *drbg,
7068c2ecf20Sopenharmony_ci			      unsigned char *buf,
7078c2ecf20Sopenharmony_ci			      unsigned int buflen,
7088c2ecf20Sopenharmony_ci			      struct list_head *addtl)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	int len = 0;
7118c2ecf20Sopenharmony_ci	int ret = 0;
7128c2ecf20Sopenharmony_ci	struct drbg_string data;
7138c2ecf20Sopenharmony_ci	LIST_HEAD(datalist);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	/* 10.1.2.5 step 2 */
7168c2ecf20Sopenharmony_ci	if (addtl && !list_empty(addtl)) {
7178c2ecf20Sopenharmony_ci		ret = drbg_hmac_update(drbg, addtl, 1);
7188c2ecf20Sopenharmony_ci		if (ret)
7198c2ecf20Sopenharmony_ci			return ret;
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
7238c2ecf20Sopenharmony_ci	list_add_tail(&data.list, &datalist);
7248c2ecf20Sopenharmony_ci	while (len < buflen) {
7258c2ecf20Sopenharmony_ci		unsigned int outlen = 0;
7268c2ecf20Sopenharmony_ci		/* 10.1.2.5 step 4.1 */
7278c2ecf20Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
7288c2ecf20Sopenharmony_ci		if (ret)
7298c2ecf20Sopenharmony_ci			return ret;
7308c2ecf20Sopenharmony_ci		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
7318c2ecf20Sopenharmony_ci			  drbg_blocklen(drbg) : (buflen - len);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci		/* 10.1.2.5 step 4.2 */
7348c2ecf20Sopenharmony_ci		memcpy(buf + len, drbg->V, outlen);
7358c2ecf20Sopenharmony_ci		len += outlen;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	/* 10.1.2.5 step 6 */
7398c2ecf20Sopenharmony_ci	if (addtl && !list_empty(addtl))
7408c2ecf20Sopenharmony_ci		ret = drbg_hmac_update(drbg, addtl, 1);
7418c2ecf20Sopenharmony_ci	else
7428c2ecf20Sopenharmony_ci		ret = drbg_hmac_update(drbg, NULL, 1);
7438c2ecf20Sopenharmony_ci	if (ret)
7448c2ecf20Sopenharmony_ci		return ret;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	return len;
7478c2ecf20Sopenharmony_ci}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_cistatic const struct drbg_state_ops drbg_hmac_ops = {
7508c2ecf20Sopenharmony_ci	.update		= drbg_hmac_update,
7518c2ecf20Sopenharmony_ci	.generate	= drbg_hmac_generate,
7528c2ecf20Sopenharmony_ci	.crypto_init	= drbg_init_hash_kernel,
7538c2ecf20Sopenharmony_ci	.crypto_fini	= drbg_fini_hash_kernel,
7548c2ecf20Sopenharmony_ci};
7558c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci/******************************************************************
7588c2ecf20Sopenharmony_ci * Hash DRBG callback functions
7598c2ecf20Sopenharmony_ci ******************************************************************/
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
7628c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_HASH_STRING "HASH "
7638c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha512");
7648c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha512");
7658c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha384");
7668c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha384");
7678c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha256");
7688c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha256");
7698c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_pr_sha1");
7708c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("drbg_nopr_sha1");
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci/*
7738c2ecf20Sopenharmony_ci * Increment buffer
7748c2ecf20Sopenharmony_ci *
7758c2ecf20Sopenharmony_ci * @dst buffer to increment
7768c2ecf20Sopenharmony_ci * @add value to add
7778c2ecf20Sopenharmony_ci */
7788c2ecf20Sopenharmony_cistatic inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
7798c2ecf20Sopenharmony_ci				const unsigned char *add, size_t addlen)
7808c2ecf20Sopenharmony_ci{
7818c2ecf20Sopenharmony_ci	/* implied: dstlen > addlen */
7828c2ecf20Sopenharmony_ci	unsigned char *dstptr;
7838c2ecf20Sopenharmony_ci	const unsigned char *addptr;
7848c2ecf20Sopenharmony_ci	unsigned int remainder = 0;
7858c2ecf20Sopenharmony_ci	size_t len = addlen;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	dstptr = dst + (dstlen-1);
7888c2ecf20Sopenharmony_ci	addptr = add + (addlen-1);
7898c2ecf20Sopenharmony_ci	while (len) {
7908c2ecf20Sopenharmony_ci		remainder += *dstptr + *addptr;
7918c2ecf20Sopenharmony_ci		*dstptr = remainder & 0xff;
7928c2ecf20Sopenharmony_ci		remainder >>= 8;
7938c2ecf20Sopenharmony_ci		len--; dstptr--; addptr--;
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci	len = dstlen - addlen;
7968c2ecf20Sopenharmony_ci	while (len && remainder > 0) {
7978c2ecf20Sopenharmony_ci		remainder = *dstptr + 1;
7988c2ecf20Sopenharmony_ci		*dstptr = remainder & 0xff;
7998c2ecf20Sopenharmony_ci		remainder >>= 8;
8008c2ecf20Sopenharmony_ci		len--; dstptr--;
8018c2ecf20Sopenharmony_ci	}
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci/*
8058c2ecf20Sopenharmony_ci * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
8068c2ecf20Sopenharmony_ci * interlinked, the scratchpad is used as follows:
8078c2ecf20Sopenharmony_ci * drbg_hash_update
8088c2ecf20Sopenharmony_ci *	start: drbg->scratchpad
8098c2ecf20Sopenharmony_ci *	length: drbg_statelen(drbg)
8108c2ecf20Sopenharmony_ci * drbg_hash_df:
8118c2ecf20Sopenharmony_ci *	start: drbg->scratchpad + drbg_statelen(drbg)
8128c2ecf20Sopenharmony_ci *	length: drbg_blocklen(drbg)
8138c2ecf20Sopenharmony_ci *
8148c2ecf20Sopenharmony_ci * drbg_hash_process_addtl uses the scratchpad, but fully completes
8158c2ecf20Sopenharmony_ci * before either of the functions mentioned before are invoked. Therefore,
8168c2ecf20Sopenharmony_ci * drbg_hash_process_addtl does not need to be specifically considered.
8178c2ecf20Sopenharmony_ci */
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci/* Derivation Function for Hash DRBG as defined in 10.4.1 */
8208c2ecf20Sopenharmony_cistatic int drbg_hash_df(struct drbg_state *drbg,
8218c2ecf20Sopenharmony_ci			unsigned char *outval, size_t outlen,
8228c2ecf20Sopenharmony_ci			struct list_head *entropylist)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	int ret = 0;
8258c2ecf20Sopenharmony_ci	size_t len = 0;
8268c2ecf20Sopenharmony_ci	unsigned char input[5];
8278c2ecf20Sopenharmony_ci	unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
8288c2ecf20Sopenharmony_ci	struct drbg_string data;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	/* 10.4.1 step 3 */
8318c2ecf20Sopenharmony_ci	input[0] = 1;
8328c2ecf20Sopenharmony_ci	drbg_cpu_to_be32((outlen * 8), &input[1]);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
8358c2ecf20Sopenharmony_ci	drbg_string_fill(&data, input, 5);
8368c2ecf20Sopenharmony_ci	list_add(&data.list, entropylist);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	/* 10.4.1 step 4 */
8398c2ecf20Sopenharmony_ci	while (len < outlen) {
8408c2ecf20Sopenharmony_ci		short blocklen = 0;
8418c2ecf20Sopenharmony_ci		/* 10.4.1 step 4.1 */
8428c2ecf20Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, tmp, entropylist);
8438c2ecf20Sopenharmony_ci		if (ret)
8448c2ecf20Sopenharmony_ci			goto out;
8458c2ecf20Sopenharmony_ci		/* 10.4.1 step 4.2 */
8468c2ecf20Sopenharmony_ci		input[0]++;
8478c2ecf20Sopenharmony_ci		blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
8488c2ecf20Sopenharmony_ci			    drbg_blocklen(drbg) : (outlen - len);
8498c2ecf20Sopenharmony_ci		memcpy(outval + len, tmp, blocklen);
8508c2ecf20Sopenharmony_ci		len += blocklen;
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ciout:
8548c2ecf20Sopenharmony_ci	memset(tmp, 0, drbg_blocklen(drbg));
8558c2ecf20Sopenharmony_ci	return ret;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
8598c2ecf20Sopenharmony_cistatic int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
8608c2ecf20Sopenharmony_ci			    int reseed)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	int ret = 0;
8638c2ecf20Sopenharmony_ci	struct drbg_string data1, data2;
8648c2ecf20Sopenharmony_ci	LIST_HEAD(datalist);
8658c2ecf20Sopenharmony_ci	LIST_HEAD(datalist2);
8668c2ecf20Sopenharmony_ci	unsigned char *V = drbg->scratchpad;
8678c2ecf20Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX1;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	if (!seed)
8708c2ecf20Sopenharmony_ci		return -EINVAL;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (reseed) {
8738c2ecf20Sopenharmony_ci		/* 10.1.1.3 step 1 */
8748c2ecf20Sopenharmony_ci		memcpy(V, drbg->V, drbg_statelen(drbg));
8758c2ecf20Sopenharmony_ci		drbg_string_fill(&data1, &prefix, 1);
8768c2ecf20Sopenharmony_ci		list_add_tail(&data1.list, &datalist);
8778c2ecf20Sopenharmony_ci		drbg_string_fill(&data2, V, drbg_statelen(drbg));
8788c2ecf20Sopenharmony_ci		list_add_tail(&data2.list, &datalist);
8798c2ecf20Sopenharmony_ci	}
8808c2ecf20Sopenharmony_ci	list_splice_tail(seed, &datalist);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
8838c2ecf20Sopenharmony_ci	ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
8848c2ecf20Sopenharmony_ci	if (ret)
8858c2ecf20Sopenharmony_ci		goto out;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 4  */
8888c2ecf20Sopenharmony_ci	prefix = DRBG_PREFIX0;
8898c2ecf20Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
8908c2ecf20Sopenharmony_ci	list_add_tail(&data1.list, &datalist2);
8918c2ecf20Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
8928c2ecf20Sopenharmony_ci	list_add_tail(&data2.list, &datalist2);
8938c2ecf20Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 4 */
8948c2ecf20Sopenharmony_ci	ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ciout:
8978c2ecf20Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_statelen(drbg));
8988c2ecf20Sopenharmony_ci	return ret;
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci/* processing of additional information string for Hash DRBG */
9028c2ecf20Sopenharmony_cistatic int drbg_hash_process_addtl(struct drbg_state *drbg,
9038c2ecf20Sopenharmony_ci				   struct list_head *addtl)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci	int ret = 0;
9068c2ecf20Sopenharmony_ci	struct drbg_string data1, data2;
9078c2ecf20Sopenharmony_ci	LIST_HEAD(datalist);
9088c2ecf20Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX2;
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 2 */
9118c2ecf20Sopenharmony_ci	if (!addtl || list_empty(addtl))
9128c2ecf20Sopenharmony_ci		return 0;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 2a */
9158c2ecf20Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
9168c2ecf20Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
9178c2ecf20Sopenharmony_ci	list_add_tail(&data1.list, &datalist);
9188c2ecf20Sopenharmony_ci	list_add_tail(&data2.list, &datalist);
9198c2ecf20Sopenharmony_ci	list_splice_tail(addtl, &datalist);
9208c2ecf20Sopenharmony_ci	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
9218c2ecf20Sopenharmony_ci	if (ret)
9228c2ecf20Sopenharmony_ci		goto out;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 2b */
9258c2ecf20Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
9268c2ecf20Sopenharmony_ci		     drbg->scratchpad, drbg_blocklen(drbg));
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ciout:
9298c2ecf20Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
9308c2ecf20Sopenharmony_ci	return ret;
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci/* Hashgen defined in 10.1.1.4 */
9348c2ecf20Sopenharmony_cistatic int drbg_hash_hashgen(struct drbg_state *drbg,
9358c2ecf20Sopenharmony_ci			     unsigned char *buf,
9368c2ecf20Sopenharmony_ci			     unsigned int buflen)
9378c2ecf20Sopenharmony_ci{
9388c2ecf20Sopenharmony_ci	int len = 0;
9398c2ecf20Sopenharmony_ci	int ret = 0;
9408c2ecf20Sopenharmony_ci	unsigned char *src = drbg->scratchpad;
9418c2ecf20Sopenharmony_ci	unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
9428c2ecf20Sopenharmony_ci	struct drbg_string data;
9438c2ecf20Sopenharmony_ci	LIST_HEAD(datalist);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	/* 10.1.1.4 step hashgen 2 */
9468c2ecf20Sopenharmony_ci	memcpy(src, drbg->V, drbg_statelen(drbg));
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	drbg_string_fill(&data, src, drbg_statelen(drbg));
9498c2ecf20Sopenharmony_ci	list_add_tail(&data.list, &datalist);
9508c2ecf20Sopenharmony_ci	while (len < buflen) {
9518c2ecf20Sopenharmony_ci		unsigned int outlen = 0;
9528c2ecf20Sopenharmony_ci		/* 10.1.1.4 step hashgen 4.1 */
9538c2ecf20Sopenharmony_ci		ret = drbg_kcapi_hash(drbg, dst, &datalist);
9548c2ecf20Sopenharmony_ci		if (ret) {
9558c2ecf20Sopenharmony_ci			len = ret;
9568c2ecf20Sopenharmony_ci			goto out;
9578c2ecf20Sopenharmony_ci		}
9588c2ecf20Sopenharmony_ci		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
9598c2ecf20Sopenharmony_ci			  drbg_blocklen(drbg) : (buflen - len);
9608c2ecf20Sopenharmony_ci		/* 10.1.1.4 step hashgen 4.2 */
9618c2ecf20Sopenharmony_ci		memcpy(buf + len, dst, outlen);
9628c2ecf20Sopenharmony_ci		len += outlen;
9638c2ecf20Sopenharmony_ci		/* 10.1.1.4 hashgen step 4.3 */
9648c2ecf20Sopenharmony_ci		if (len < buflen)
9658c2ecf20Sopenharmony_ci			crypto_inc(src, drbg_statelen(drbg));
9668c2ecf20Sopenharmony_ci	}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ciout:
9698c2ecf20Sopenharmony_ci	memset(drbg->scratchpad, 0,
9708c2ecf20Sopenharmony_ci	       (drbg_statelen(drbg) + drbg_blocklen(drbg)));
9718c2ecf20Sopenharmony_ci	return len;
9728c2ecf20Sopenharmony_ci}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci/* generate function for Hash DRBG as defined in  10.1.1.4 */
9758c2ecf20Sopenharmony_cistatic int drbg_hash_generate(struct drbg_state *drbg,
9768c2ecf20Sopenharmony_ci			      unsigned char *buf, unsigned int buflen,
9778c2ecf20Sopenharmony_ci			      struct list_head *addtl)
9788c2ecf20Sopenharmony_ci{
9798c2ecf20Sopenharmony_ci	int len = 0;
9808c2ecf20Sopenharmony_ci	int ret = 0;
9818c2ecf20Sopenharmony_ci	union {
9828c2ecf20Sopenharmony_ci		unsigned char req[8];
9838c2ecf20Sopenharmony_ci		__be64 req_int;
9848c2ecf20Sopenharmony_ci	} u;
9858c2ecf20Sopenharmony_ci	unsigned char prefix = DRBG_PREFIX3;
9868c2ecf20Sopenharmony_ci	struct drbg_string data1, data2;
9878c2ecf20Sopenharmony_ci	LIST_HEAD(datalist);
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 2 */
9908c2ecf20Sopenharmony_ci	ret = drbg_hash_process_addtl(drbg, addtl);
9918c2ecf20Sopenharmony_ci	if (ret)
9928c2ecf20Sopenharmony_ci		return ret;
9938c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 3 */
9948c2ecf20Sopenharmony_ci	len = drbg_hash_hashgen(drbg, buf, buflen);
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	/* this is the value H as documented in 10.1.1.4 */
9978c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 4 */
9988c2ecf20Sopenharmony_ci	drbg_string_fill(&data1, &prefix, 1);
9998c2ecf20Sopenharmony_ci	list_add_tail(&data1.list, &datalist);
10008c2ecf20Sopenharmony_ci	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
10018c2ecf20Sopenharmony_ci	list_add_tail(&data2.list, &datalist);
10028c2ecf20Sopenharmony_ci	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
10038c2ecf20Sopenharmony_ci	if (ret) {
10048c2ecf20Sopenharmony_ci		len = ret;
10058c2ecf20Sopenharmony_ci		goto out;
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 5 */
10098c2ecf20Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
10108c2ecf20Sopenharmony_ci		     drbg->scratchpad, drbg_blocklen(drbg));
10118c2ecf20Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg),
10128c2ecf20Sopenharmony_ci		     drbg->C, drbg_statelen(drbg));
10138c2ecf20Sopenharmony_ci	u.req_int = cpu_to_be64(drbg->reseed_ctr);
10148c2ecf20Sopenharmony_ci	drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8);
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ciout:
10178c2ecf20Sopenharmony_ci	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
10188c2ecf20Sopenharmony_ci	return len;
10198c2ecf20Sopenharmony_ci}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci/*
10228c2ecf20Sopenharmony_ci * scratchpad usage: as update and generate are used isolated, both
10238c2ecf20Sopenharmony_ci * can use the scratchpad
10248c2ecf20Sopenharmony_ci */
10258c2ecf20Sopenharmony_cistatic const struct drbg_state_ops drbg_hash_ops = {
10268c2ecf20Sopenharmony_ci	.update		= drbg_hash_update,
10278c2ecf20Sopenharmony_ci	.generate	= drbg_hash_generate,
10288c2ecf20Sopenharmony_ci	.crypto_init	= drbg_init_hash_kernel,
10298c2ecf20Sopenharmony_ci	.crypto_fini	= drbg_fini_hash_kernel,
10308c2ecf20Sopenharmony_ci};
10318c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci/******************************************************************
10348c2ecf20Sopenharmony_ci * Functions common for DRBG implementations
10358c2ecf20Sopenharmony_ci ******************************************************************/
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
10388c2ecf20Sopenharmony_ci			      int reseed, enum drbg_seed_state new_seed_state)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	int ret = drbg->d_ops->update(drbg, seed, reseed);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	if (ret)
10438c2ecf20Sopenharmony_ci		return ret;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	drbg->seeded = new_seed_state;
10468c2ecf20Sopenharmony_ci	/* 10.1.1.2 / 10.1.1.3 step 5 */
10478c2ecf20Sopenharmony_ci	drbg->reseed_ctr = 1;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	switch (drbg->seeded) {
10508c2ecf20Sopenharmony_ci	case DRBG_SEED_STATE_UNSEEDED:
10518c2ecf20Sopenharmony_ci		/* Impossible, but handle it to silence compiler warnings. */
10528c2ecf20Sopenharmony_ci		fallthrough;
10538c2ecf20Sopenharmony_ci	case DRBG_SEED_STATE_PARTIAL:
10548c2ecf20Sopenharmony_ci		/*
10558c2ecf20Sopenharmony_ci		 * Require frequent reseeds until the seed source is
10568c2ecf20Sopenharmony_ci		 * fully initialized.
10578c2ecf20Sopenharmony_ci		 */
10588c2ecf20Sopenharmony_ci		drbg->reseed_threshold = 50;
10598c2ecf20Sopenharmony_ci		break;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	case DRBG_SEED_STATE_FULL:
10628c2ecf20Sopenharmony_ci		/*
10638c2ecf20Sopenharmony_ci		 * Seed source has become fully initialized, frequent
10648c2ecf20Sopenharmony_ci		 * reseeds no longer required.
10658c2ecf20Sopenharmony_ci		 */
10668c2ecf20Sopenharmony_ci		drbg->reseed_threshold = drbg_max_requests(drbg);
10678c2ecf20Sopenharmony_ci		break;
10688c2ecf20Sopenharmony_ci	}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	return ret;
10718c2ecf20Sopenharmony_ci}
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_cistatic inline int drbg_get_random_bytes(struct drbg_state *drbg,
10748c2ecf20Sopenharmony_ci					unsigned char *entropy,
10758c2ecf20Sopenharmony_ci					unsigned int entropylen)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	int ret;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	do {
10808c2ecf20Sopenharmony_ci		get_random_bytes(entropy, entropylen);
10818c2ecf20Sopenharmony_ci		ret = drbg_fips_continuous_test(drbg, entropy);
10828c2ecf20Sopenharmony_ci		if (ret && ret != -EAGAIN)
10838c2ecf20Sopenharmony_ci			return ret;
10848c2ecf20Sopenharmony_ci	} while (ret);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	return 0;
10878c2ecf20Sopenharmony_ci}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_cistatic int drbg_seed_from_random(struct drbg_state *drbg)
10908c2ecf20Sopenharmony_ci{
10918c2ecf20Sopenharmony_ci	struct drbg_string data;
10928c2ecf20Sopenharmony_ci	LIST_HEAD(seedlist);
10938c2ecf20Sopenharmony_ci	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
10948c2ecf20Sopenharmony_ci	unsigned char entropy[32];
10958c2ecf20Sopenharmony_ci	int ret;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	BUG_ON(!entropylen);
10988c2ecf20Sopenharmony_ci	BUG_ON(entropylen > sizeof(entropy));
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	drbg_string_fill(&data, entropy, entropylen);
11018c2ecf20Sopenharmony_ci	list_add_tail(&data.list, &seedlist);
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	ret = drbg_get_random_bytes(drbg, entropy, entropylen);
11048c2ecf20Sopenharmony_ci	if (ret)
11058c2ecf20Sopenharmony_ci		goto out;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ciout:
11108c2ecf20Sopenharmony_ci	memzero_explicit(entropy, entropylen);
11118c2ecf20Sopenharmony_ci	return ret;
11128c2ecf20Sopenharmony_ci}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci/*
11158c2ecf20Sopenharmony_ci * Seeding or reseeding of the DRBG
11168c2ecf20Sopenharmony_ci *
11178c2ecf20Sopenharmony_ci * @drbg: DRBG state struct
11188c2ecf20Sopenharmony_ci * @pers: personalization / additional information buffer
11198c2ecf20Sopenharmony_ci * @reseed: 0 for initial seed process, 1 for reseeding
11208c2ecf20Sopenharmony_ci *
11218c2ecf20Sopenharmony_ci * return:
11228c2ecf20Sopenharmony_ci *	0 on success
11238c2ecf20Sopenharmony_ci *	error value otherwise
11248c2ecf20Sopenharmony_ci */
11258c2ecf20Sopenharmony_cistatic int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
11268c2ecf20Sopenharmony_ci		     bool reseed)
11278c2ecf20Sopenharmony_ci{
11288c2ecf20Sopenharmony_ci	int ret;
11298c2ecf20Sopenharmony_ci	unsigned char entropy[((32 + 16) * 2)];
11308c2ecf20Sopenharmony_ci	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
11318c2ecf20Sopenharmony_ci	struct drbg_string data1;
11328c2ecf20Sopenharmony_ci	LIST_HEAD(seedlist);
11338c2ecf20Sopenharmony_ci	enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	/* 9.1 / 9.2 / 9.3.1 step 3 */
11368c2ecf20Sopenharmony_ci	if (pers && pers->len > (drbg_max_addtl(drbg))) {
11378c2ecf20Sopenharmony_ci		pr_devel("DRBG: personalization string too long %zu\n",
11388c2ecf20Sopenharmony_ci			 pers->len);
11398c2ecf20Sopenharmony_ci		return -EINVAL;
11408c2ecf20Sopenharmony_ci	}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	if (list_empty(&drbg->test_data.list)) {
11438c2ecf20Sopenharmony_ci		drbg_string_fill(&data1, drbg->test_data.buf,
11448c2ecf20Sopenharmony_ci				 drbg->test_data.len);
11458c2ecf20Sopenharmony_ci		pr_devel("DRBG: using test entropy\n");
11468c2ecf20Sopenharmony_ci	} else {
11478c2ecf20Sopenharmony_ci		/*
11488c2ecf20Sopenharmony_ci		 * Gather entropy equal to the security strength of the DRBG.
11498c2ecf20Sopenharmony_ci		 * With a derivation function, a nonce is required in addition
11508c2ecf20Sopenharmony_ci		 * to the entropy. A nonce must be at least 1/2 of the security
11518c2ecf20Sopenharmony_ci		 * strength of the DRBG in size. Thus, entropy + nonce is 3/2
11528c2ecf20Sopenharmony_ci		 * of the strength. The consideration of a nonce is only
11538c2ecf20Sopenharmony_ci		 * applicable during initial seeding.
11548c2ecf20Sopenharmony_ci		 */
11558c2ecf20Sopenharmony_ci		BUG_ON(!entropylen);
11568c2ecf20Sopenharmony_ci		if (!reseed)
11578c2ecf20Sopenharmony_ci			entropylen = ((entropylen + 1) / 2) * 3;
11588c2ecf20Sopenharmony_ci		BUG_ON((entropylen * 2) > sizeof(entropy));
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci		/* Get seed from in-kernel /dev/urandom */
11618c2ecf20Sopenharmony_ci		if (!rng_is_initialized())
11628c2ecf20Sopenharmony_ci			new_seed_state = DRBG_SEED_STATE_PARTIAL;
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci		ret = drbg_get_random_bytes(drbg, entropy, entropylen);
11658c2ecf20Sopenharmony_ci		if (ret)
11668c2ecf20Sopenharmony_ci			goto out;
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci		if (!drbg->jent) {
11698c2ecf20Sopenharmony_ci			drbg_string_fill(&data1, entropy, entropylen);
11708c2ecf20Sopenharmony_ci			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
11718c2ecf20Sopenharmony_ci				 entropylen);
11728c2ecf20Sopenharmony_ci		} else {
11738c2ecf20Sopenharmony_ci			/* Get seed from Jitter RNG */
11748c2ecf20Sopenharmony_ci			ret = crypto_rng_get_bytes(drbg->jent,
11758c2ecf20Sopenharmony_ci						   entropy + entropylen,
11768c2ecf20Sopenharmony_ci						   entropylen);
11778c2ecf20Sopenharmony_ci			if (ret) {
11788c2ecf20Sopenharmony_ci				pr_devel("DRBG: jent failed with %d\n", ret);
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci				/*
11818c2ecf20Sopenharmony_ci				 * Do not treat the transient failure of the
11828c2ecf20Sopenharmony_ci				 * Jitter RNG as an error that needs to be
11838c2ecf20Sopenharmony_ci				 * reported. The combined number of the
11848c2ecf20Sopenharmony_ci				 * maximum reseed threshold times the maximum
11858c2ecf20Sopenharmony_ci				 * number of Jitter RNG transient errors is
11868c2ecf20Sopenharmony_ci				 * less than the reseed threshold required by
11878c2ecf20Sopenharmony_ci				 * SP800-90A allowing us to treat the
11888c2ecf20Sopenharmony_ci				 * transient errors as such.
11898c2ecf20Sopenharmony_ci				 *
11908c2ecf20Sopenharmony_ci				 * However, we mandate that at least the first
11918c2ecf20Sopenharmony_ci				 * seeding operation must succeed with the
11928c2ecf20Sopenharmony_ci				 * Jitter RNG.
11938c2ecf20Sopenharmony_ci				 */
11948c2ecf20Sopenharmony_ci				if (!reseed || ret != -EAGAIN)
11958c2ecf20Sopenharmony_ci					goto out;
11968c2ecf20Sopenharmony_ci			}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci			drbg_string_fill(&data1, entropy, entropylen * 2);
11998c2ecf20Sopenharmony_ci			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
12008c2ecf20Sopenharmony_ci				 entropylen * 2);
12018c2ecf20Sopenharmony_ci		}
12028c2ecf20Sopenharmony_ci	}
12038c2ecf20Sopenharmony_ci	list_add_tail(&data1.list, &seedlist);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	/*
12068c2ecf20Sopenharmony_ci	 * concatenation of entropy with personalization str / addtl input)
12078c2ecf20Sopenharmony_ci	 * the variable pers is directly handed in by the caller, so check its
12088c2ecf20Sopenharmony_ci	 * contents whether it is appropriate
12098c2ecf20Sopenharmony_ci	 */
12108c2ecf20Sopenharmony_ci	if (pers && pers->buf && 0 < pers->len) {
12118c2ecf20Sopenharmony_ci		list_add_tail(&pers->list, &seedlist);
12128c2ecf20Sopenharmony_ci		pr_devel("DRBG: using personalization string\n");
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	if (!reseed) {
12168c2ecf20Sopenharmony_ci		memset(drbg->V, 0, drbg_statelen(drbg));
12178c2ecf20Sopenharmony_ci		memset(drbg->C, 0, drbg_statelen(drbg));
12188c2ecf20Sopenharmony_ci	}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ciout:
12238c2ecf20Sopenharmony_ci	memzero_explicit(entropy, entropylen * 2);
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	return ret;
12268c2ecf20Sopenharmony_ci}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci/* Free all substructures in a DRBG state without the DRBG state structure */
12298c2ecf20Sopenharmony_cistatic inline void drbg_dealloc_state(struct drbg_state *drbg)
12308c2ecf20Sopenharmony_ci{
12318c2ecf20Sopenharmony_ci	if (!drbg)
12328c2ecf20Sopenharmony_ci		return;
12338c2ecf20Sopenharmony_ci	kfree_sensitive(drbg->Vbuf);
12348c2ecf20Sopenharmony_ci	drbg->Vbuf = NULL;
12358c2ecf20Sopenharmony_ci	drbg->V = NULL;
12368c2ecf20Sopenharmony_ci	kfree_sensitive(drbg->Cbuf);
12378c2ecf20Sopenharmony_ci	drbg->Cbuf = NULL;
12388c2ecf20Sopenharmony_ci	drbg->C = NULL;
12398c2ecf20Sopenharmony_ci	kfree_sensitive(drbg->scratchpadbuf);
12408c2ecf20Sopenharmony_ci	drbg->scratchpadbuf = NULL;
12418c2ecf20Sopenharmony_ci	drbg->reseed_ctr = 0;
12428c2ecf20Sopenharmony_ci	drbg->d_ops = NULL;
12438c2ecf20Sopenharmony_ci	drbg->core = NULL;
12448c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
12458c2ecf20Sopenharmony_ci		kfree_sensitive(drbg->prev);
12468c2ecf20Sopenharmony_ci		drbg->prev = NULL;
12478c2ecf20Sopenharmony_ci		drbg->fips_primed = false;
12488c2ecf20Sopenharmony_ci	}
12498c2ecf20Sopenharmony_ci}
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci/*
12528c2ecf20Sopenharmony_ci * Allocate all sub-structures for a DRBG state.
12538c2ecf20Sopenharmony_ci * The DRBG state structure must already be allocated.
12548c2ecf20Sopenharmony_ci */
12558c2ecf20Sopenharmony_cistatic inline int drbg_alloc_state(struct drbg_state *drbg)
12568c2ecf20Sopenharmony_ci{
12578c2ecf20Sopenharmony_ci	int ret = -ENOMEM;
12588c2ecf20Sopenharmony_ci	unsigned int sb_size = 0;
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	switch (drbg->core->flags & DRBG_TYPE_MASK) {
12618c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HMAC
12628c2ecf20Sopenharmony_ci	case DRBG_HMAC:
12638c2ecf20Sopenharmony_ci		drbg->d_ops = &drbg_hmac_ops;
12648c2ecf20Sopenharmony_ci		break;
12658c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HMAC */
12668c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_HASH
12678c2ecf20Sopenharmony_ci	case DRBG_HASH:
12688c2ecf20Sopenharmony_ci		drbg->d_ops = &drbg_hash_ops;
12698c2ecf20Sopenharmony_ci		break;
12708c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_HASH */
12718c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
12728c2ecf20Sopenharmony_ci	case DRBG_CTR:
12738c2ecf20Sopenharmony_ci		drbg->d_ops = &drbg_ctr_ops;
12748c2ecf20Sopenharmony_ci		break;
12758c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
12768c2ecf20Sopenharmony_ci	default:
12778c2ecf20Sopenharmony_ci		ret = -EOPNOTSUPP;
12788c2ecf20Sopenharmony_ci		goto err;
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	ret = drbg->d_ops->crypto_init(drbg);
12828c2ecf20Sopenharmony_ci	if (ret < 0)
12838c2ecf20Sopenharmony_ci		goto err;
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
12868c2ecf20Sopenharmony_ci	if (!drbg->Vbuf) {
12878c2ecf20Sopenharmony_ci		ret = -ENOMEM;
12888c2ecf20Sopenharmony_ci		goto fini;
12898c2ecf20Sopenharmony_ci	}
12908c2ecf20Sopenharmony_ci	drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
12918c2ecf20Sopenharmony_ci	drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
12928c2ecf20Sopenharmony_ci	if (!drbg->Cbuf) {
12938c2ecf20Sopenharmony_ci		ret = -ENOMEM;
12948c2ecf20Sopenharmony_ci		goto fini;
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci	drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
12978c2ecf20Sopenharmony_ci	/* scratchpad is only generated for CTR and Hash */
12988c2ecf20Sopenharmony_ci	if (drbg->core->flags & DRBG_HMAC)
12998c2ecf20Sopenharmony_ci		sb_size = 0;
13008c2ecf20Sopenharmony_ci	else if (drbg->core->flags & DRBG_CTR)
13018c2ecf20Sopenharmony_ci		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
13028c2ecf20Sopenharmony_ci			  drbg_statelen(drbg) +	/* df_data */
13038c2ecf20Sopenharmony_ci			  drbg_blocklen(drbg) +	/* pad */
13048c2ecf20Sopenharmony_ci			  drbg_blocklen(drbg) +	/* iv */
13058c2ecf20Sopenharmony_ci			  drbg_statelen(drbg) + drbg_blocklen(drbg); /* temp */
13068c2ecf20Sopenharmony_ci	else
13078c2ecf20Sopenharmony_ci		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	if (0 < sb_size) {
13108c2ecf20Sopenharmony_ci		drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL);
13118c2ecf20Sopenharmony_ci		if (!drbg->scratchpadbuf) {
13128c2ecf20Sopenharmony_ci			ret = -ENOMEM;
13138c2ecf20Sopenharmony_ci			goto fini;
13148c2ecf20Sopenharmony_ci		}
13158c2ecf20Sopenharmony_ci		drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
13168c2ecf20Sopenharmony_ci	}
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
13198c2ecf20Sopenharmony_ci		drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
13208c2ecf20Sopenharmony_ci				     GFP_KERNEL);
13218c2ecf20Sopenharmony_ci		if (!drbg->prev) {
13228c2ecf20Sopenharmony_ci			ret = -ENOMEM;
13238c2ecf20Sopenharmony_ci			goto fini;
13248c2ecf20Sopenharmony_ci		}
13258c2ecf20Sopenharmony_ci		drbg->fips_primed = false;
13268c2ecf20Sopenharmony_ci	}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	return 0;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_cifini:
13318c2ecf20Sopenharmony_ci	drbg->d_ops->crypto_fini(drbg);
13328c2ecf20Sopenharmony_cierr:
13338c2ecf20Sopenharmony_ci	drbg_dealloc_state(drbg);
13348c2ecf20Sopenharmony_ci	return ret;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci/*************************************************************************
13388c2ecf20Sopenharmony_ci * DRBG interface functions
13398c2ecf20Sopenharmony_ci *************************************************************************/
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci/*
13428c2ecf20Sopenharmony_ci * DRBG generate function as required by SP800-90A - this function
13438c2ecf20Sopenharmony_ci * generates random numbers
13448c2ecf20Sopenharmony_ci *
13458c2ecf20Sopenharmony_ci * @drbg DRBG state handle
13468c2ecf20Sopenharmony_ci * @buf Buffer where to store the random numbers -- the buffer must already
13478c2ecf20Sopenharmony_ci *      be pre-allocated by caller
13488c2ecf20Sopenharmony_ci * @buflen Length of output buffer - this value defines the number of random
13498c2ecf20Sopenharmony_ci *	   bytes pulled from DRBG
13508c2ecf20Sopenharmony_ci * @addtl Additional input that is mixed into state, may be NULL -- note
13518c2ecf20Sopenharmony_ci *	  the entropy is pulled by the DRBG internally unconditionally
13528c2ecf20Sopenharmony_ci *	  as defined in SP800-90A. The additional input is mixed into
13538c2ecf20Sopenharmony_ci *	  the state in addition to the pulled entropy.
13548c2ecf20Sopenharmony_ci *
13558c2ecf20Sopenharmony_ci * return: 0 when all bytes are generated; < 0 in case of an error
13568c2ecf20Sopenharmony_ci */
13578c2ecf20Sopenharmony_cistatic int drbg_generate(struct drbg_state *drbg,
13588c2ecf20Sopenharmony_ci			 unsigned char *buf, unsigned int buflen,
13598c2ecf20Sopenharmony_ci			 struct drbg_string *addtl)
13608c2ecf20Sopenharmony_ci{
13618c2ecf20Sopenharmony_ci	int len = 0;
13628c2ecf20Sopenharmony_ci	LIST_HEAD(addtllist);
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	if (!drbg->core) {
13658c2ecf20Sopenharmony_ci		pr_devel("DRBG: not yet seeded\n");
13668c2ecf20Sopenharmony_ci		return -EINVAL;
13678c2ecf20Sopenharmony_ci	}
13688c2ecf20Sopenharmony_ci	if (0 == buflen || !buf) {
13698c2ecf20Sopenharmony_ci		pr_devel("DRBG: no output buffer provided\n");
13708c2ecf20Sopenharmony_ci		return -EINVAL;
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci	if (addtl && NULL == addtl->buf && 0 < addtl->len) {
13738c2ecf20Sopenharmony_ci		pr_devel("DRBG: wrong format of additional information\n");
13748c2ecf20Sopenharmony_ci		return -EINVAL;
13758c2ecf20Sopenharmony_ci	}
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	/* 9.3.1 step 2 */
13788c2ecf20Sopenharmony_ci	len = -EINVAL;
13798c2ecf20Sopenharmony_ci	if (buflen > (drbg_max_request_bytes(drbg))) {
13808c2ecf20Sopenharmony_ci		pr_devel("DRBG: requested random numbers too large %u\n",
13818c2ecf20Sopenharmony_ci			 buflen);
13828c2ecf20Sopenharmony_ci		goto err;
13838c2ecf20Sopenharmony_ci	}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	/* 9.3.1 step 3 is implicit with the chosen DRBG */
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci	/* 9.3.1 step 4 */
13888c2ecf20Sopenharmony_ci	if (addtl && addtl->len > (drbg_max_addtl(drbg))) {
13898c2ecf20Sopenharmony_ci		pr_devel("DRBG: additional information string too long %zu\n",
13908c2ecf20Sopenharmony_ci			 addtl->len);
13918c2ecf20Sopenharmony_ci		goto err;
13928c2ecf20Sopenharmony_ci	}
13938c2ecf20Sopenharmony_ci	/* 9.3.1 step 5 is implicit with the chosen DRBG */
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	/*
13968c2ecf20Sopenharmony_ci	 * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented
13978c2ecf20Sopenharmony_ci	 * here. The spec is a bit convoluted here, we make it simpler.
13988c2ecf20Sopenharmony_ci	 */
13998c2ecf20Sopenharmony_ci	if (drbg->reseed_threshold < drbg->reseed_ctr)
14008c2ecf20Sopenharmony_ci		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
14038c2ecf20Sopenharmony_ci		pr_devel("DRBG: reseeding before generation (prediction "
14048c2ecf20Sopenharmony_ci			 "resistance: %s, state %s)\n",
14058c2ecf20Sopenharmony_ci			 drbg->pr ? "true" : "false",
14068c2ecf20Sopenharmony_ci			 (drbg->seeded ==  DRBG_SEED_STATE_FULL ?
14078c2ecf20Sopenharmony_ci			  "seeded" : "unseeded"));
14088c2ecf20Sopenharmony_ci		/* 9.3.1 steps 7.1 through 7.3 */
14098c2ecf20Sopenharmony_ci		len = drbg_seed(drbg, addtl, true);
14108c2ecf20Sopenharmony_ci		if (len)
14118c2ecf20Sopenharmony_ci			goto err;
14128c2ecf20Sopenharmony_ci		/* 9.3.1 step 7.4 */
14138c2ecf20Sopenharmony_ci		addtl = NULL;
14148c2ecf20Sopenharmony_ci	} else if (rng_is_initialized() &&
14158c2ecf20Sopenharmony_ci		   drbg->seeded == DRBG_SEED_STATE_PARTIAL) {
14168c2ecf20Sopenharmony_ci		len = drbg_seed_from_random(drbg);
14178c2ecf20Sopenharmony_ci		if (len)
14188c2ecf20Sopenharmony_ci			goto err;
14198c2ecf20Sopenharmony_ci	}
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	if (addtl && 0 < addtl->len)
14228c2ecf20Sopenharmony_ci		list_add_tail(&addtl->list, &addtllist);
14238c2ecf20Sopenharmony_ci	/* 9.3.1 step 8 and 10 */
14248c2ecf20Sopenharmony_ci	len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist);
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
14278c2ecf20Sopenharmony_ci	drbg->reseed_ctr++;
14288c2ecf20Sopenharmony_ci	if (0 >= len)
14298c2ecf20Sopenharmony_ci		goto err;
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	/*
14328c2ecf20Sopenharmony_ci	 * Section 11.3.3 requires to re-perform self tests after some
14338c2ecf20Sopenharmony_ci	 * generated random numbers. The chosen value after which self
14348c2ecf20Sopenharmony_ci	 * test is performed is arbitrary, but it should be reasonable.
14358c2ecf20Sopenharmony_ci	 * However, we do not perform the self tests because of the following
14368c2ecf20Sopenharmony_ci	 * reasons: it is mathematically impossible that the initial self tests
14378c2ecf20Sopenharmony_ci	 * were successfully and the following are not. If the initial would
14388c2ecf20Sopenharmony_ci	 * pass and the following would not, the kernel integrity is violated.
14398c2ecf20Sopenharmony_ci	 * In this case, the entire kernel operation is questionable and it
14408c2ecf20Sopenharmony_ci	 * is unlikely that the integrity violation only affects the
14418c2ecf20Sopenharmony_ci	 * correct operation of the DRBG.
14428c2ecf20Sopenharmony_ci	 *
14438c2ecf20Sopenharmony_ci	 * Albeit the following code is commented out, it is provided in
14448c2ecf20Sopenharmony_ci	 * case somebody has a need to implement the test of 11.3.3.
14458c2ecf20Sopenharmony_ci	 */
14468c2ecf20Sopenharmony_ci#if 0
14478c2ecf20Sopenharmony_ci	if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) {
14488c2ecf20Sopenharmony_ci		int err = 0;
14498c2ecf20Sopenharmony_ci		pr_devel("DRBG: start to perform self test\n");
14508c2ecf20Sopenharmony_ci		if (drbg->core->flags & DRBG_HMAC)
14518c2ecf20Sopenharmony_ci			err = alg_test("drbg_pr_hmac_sha256",
14528c2ecf20Sopenharmony_ci				       "drbg_pr_hmac_sha256", 0, 0);
14538c2ecf20Sopenharmony_ci		else if (drbg->core->flags & DRBG_CTR)
14548c2ecf20Sopenharmony_ci			err = alg_test("drbg_pr_ctr_aes128",
14558c2ecf20Sopenharmony_ci				       "drbg_pr_ctr_aes128", 0, 0);
14568c2ecf20Sopenharmony_ci		else
14578c2ecf20Sopenharmony_ci			err = alg_test("drbg_pr_sha256",
14588c2ecf20Sopenharmony_ci				       "drbg_pr_sha256", 0, 0);
14598c2ecf20Sopenharmony_ci		if (err) {
14608c2ecf20Sopenharmony_ci			pr_err("DRBG: periodical self test failed\n");
14618c2ecf20Sopenharmony_ci			/*
14628c2ecf20Sopenharmony_ci			 * uninstantiate implies that from now on, only errors
14638c2ecf20Sopenharmony_ci			 * are returned when reusing this DRBG cipher handle
14648c2ecf20Sopenharmony_ci			 */
14658c2ecf20Sopenharmony_ci			drbg_uninstantiate(drbg);
14668c2ecf20Sopenharmony_ci			return 0;
14678c2ecf20Sopenharmony_ci		} else {
14688c2ecf20Sopenharmony_ci			pr_devel("DRBG: self test successful\n");
14698c2ecf20Sopenharmony_ci		}
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ci#endif
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	/*
14748c2ecf20Sopenharmony_ci	 * All operations were successful, return 0 as mandated by
14758c2ecf20Sopenharmony_ci	 * the kernel crypto API interface.
14768c2ecf20Sopenharmony_ci	 */
14778c2ecf20Sopenharmony_ci	len = 0;
14788c2ecf20Sopenharmony_cierr:
14798c2ecf20Sopenharmony_ci	return len;
14808c2ecf20Sopenharmony_ci}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci/*
14838c2ecf20Sopenharmony_ci * Wrapper around drbg_generate which can pull arbitrary long strings
14848c2ecf20Sopenharmony_ci * from the DRBG without hitting the maximum request limitation.
14858c2ecf20Sopenharmony_ci *
14868c2ecf20Sopenharmony_ci * Parameters: see drbg_generate
14878c2ecf20Sopenharmony_ci * Return codes: see drbg_generate -- if one drbg_generate request fails,
14888c2ecf20Sopenharmony_ci *		 the entire drbg_generate_long request fails
14898c2ecf20Sopenharmony_ci */
14908c2ecf20Sopenharmony_cistatic int drbg_generate_long(struct drbg_state *drbg,
14918c2ecf20Sopenharmony_ci			      unsigned char *buf, unsigned int buflen,
14928c2ecf20Sopenharmony_ci			      struct drbg_string *addtl)
14938c2ecf20Sopenharmony_ci{
14948c2ecf20Sopenharmony_ci	unsigned int len = 0;
14958c2ecf20Sopenharmony_ci	unsigned int slice = 0;
14968c2ecf20Sopenharmony_ci	do {
14978c2ecf20Sopenharmony_ci		int err = 0;
14988c2ecf20Sopenharmony_ci		unsigned int chunk = 0;
14998c2ecf20Sopenharmony_ci		slice = ((buflen - len) / drbg_max_request_bytes(drbg));
15008c2ecf20Sopenharmony_ci		chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
15018c2ecf20Sopenharmony_ci		mutex_lock(&drbg->drbg_mutex);
15028c2ecf20Sopenharmony_ci		err = drbg_generate(drbg, buf + len, chunk, addtl);
15038c2ecf20Sopenharmony_ci		mutex_unlock(&drbg->drbg_mutex);
15048c2ecf20Sopenharmony_ci		if (0 > err)
15058c2ecf20Sopenharmony_ci			return err;
15068c2ecf20Sopenharmony_ci		len += chunk;
15078c2ecf20Sopenharmony_ci	} while (slice > 0 && (len < buflen));
15088c2ecf20Sopenharmony_ci	return 0;
15098c2ecf20Sopenharmony_ci}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_cistatic int drbg_prepare_hrng(struct drbg_state *drbg)
15128c2ecf20Sopenharmony_ci{
15138c2ecf20Sopenharmony_ci	/* We do not need an HRNG in test mode. */
15148c2ecf20Sopenharmony_ci	if (list_empty(&drbg->test_data.list))
15158c2ecf20Sopenharmony_ci		return 0;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
15188c2ecf20Sopenharmony_ci	if (IS_ERR(drbg->jent)) {
15198c2ecf20Sopenharmony_ci		const int err = PTR_ERR(drbg->jent);
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci		drbg->jent = NULL;
15228c2ecf20Sopenharmony_ci		if (fips_enabled)
15238c2ecf20Sopenharmony_ci			return err;
15248c2ecf20Sopenharmony_ci		pr_info("DRBG: Continuing without Jitter RNG\n");
15258c2ecf20Sopenharmony_ci	}
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	return 0;
15288c2ecf20Sopenharmony_ci}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci/*
15318c2ecf20Sopenharmony_ci * DRBG instantiation function as required by SP800-90A - this function
15328c2ecf20Sopenharmony_ci * sets up the DRBG handle, performs the initial seeding and all sanity
15338c2ecf20Sopenharmony_ci * checks required by SP800-90A
15348c2ecf20Sopenharmony_ci *
15358c2ecf20Sopenharmony_ci * @drbg memory of state -- if NULL, new memory is allocated
15368c2ecf20Sopenharmony_ci * @pers Personalization string that is mixed into state, may be NULL -- note
15378c2ecf20Sopenharmony_ci *	 the entropy is pulled by the DRBG internally unconditionally
15388c2ecf20Sopenharmony_ci *	 as defined in SP800-90A. The additional input is mixed into
15398c2ecf20Sopenharmony_ci *	 the state in addition to the pulled entropy.
15408c2ecf20Sopenharmony_ci * @coreref reference to core
15418c2ecf20Sopenharmony_ci * @pr prediction resistance enabled
15428c2ecf20Sopenharmony_ci *
15438c2ecf20Sopenharmony_ci * return
15448c2ecf20Sopenharmony_ci *	0 on success
15458c2ecf20Sopenharmony_ci *	error value otherwise
15468c2ecf20Sopenharmony_ci */
15478c2ecf20Sopenharmony_cistatic int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
15488c2ecf20Sopenharmony_ci			    int coreref, bool pr)
15498c2ecf20Sopenharmony_ci{
15508c2ecf20Sopenharmony_ci	int ret;
15518c2ecf20Sopenharmony_ci	bool reseed = true;
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
15548c2ecf20Sopenharmony_ci		 "%s\n", coreref, pr ? "enabled" : "disabled");
15558c2ecf20Sopenharmony_ci	mutex_lock(&drbg->drbg_mutex);
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	/* 9.1 step 1 is implicit with the selected DRBG type */
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	/*
15608c2ecf20Sopenharmony_ci	 * 9.1 step 2 is implicit as caller can select prediction resistance
15618c2ecf20Sopenharmony_ci	 * and the flag is copied into drbg->flags --
15628c2ecf20Sopenharmony_ci	 * all DRBG types support prediction resistance
15638c2ecf20Sopenharmony_ci	 */
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci	/* 9.1 step 4 is implicit in  drbg_sec_strength */
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	if (!drbg->core) {
15688c2ecf20Sopenharmony_ci		drbg->core = &drbg_cores[coreref];
15698c2ecf20Sopenharmony_ci		drbg->pr = pr;
15708c2ecf20Sopenharmony_ci		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
15718c2ecf20Sopenharmony_ci		drbg->reseed_threshold = drbg_max_requests(drbg);
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci		ret = drbg_alloc_state(drbg);
15748c2ecf20Sopenharmony_ci		if (ret)
15758c2ecf20Sopenharmony_ci			goto unlock;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci		ret = drbg_prepare_hrng(drbg);
15788c2ecf20Sopenharmony_ci		if (ret)
15798c2ecf20Sopenharmony_ci			goto free_everything;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci		reseed = false;
15828c2ecf20Sopenharmony_ci	}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	ret = drbg_seed(drbg, pers, reseed);
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	if (ret && !reseed)
15878c2ecf20Sopenharmony_ci		goto free_everything;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
15908c2ecf20Sopenharmony_ci	return ret;
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ciunlock:
15938c2ecf20Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
15948c2ecf20Sopenharmony_ci	return ret;
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_cifree_everything:
15978c2ecf20Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
15988c2ecf20Sopenharmony_ci	drbg_uninstantiate(drbg);
15998c2ecf20Sopenharmony_ci	return ret;
16008c2ecf20Sopenharmony_ci}
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci/*
16038c2ecf20Sopenharmony_ci * DRBG uninstantiate function as required by SP800-90A - this function
16048c2ecf20Sopenharmony_ci * frees all buffers and the DRBG handle
16058c2ecf20Sopenharmony_ci *
16068c2ecf20Sopenharmony_ci * @drbg DRBG state handle
16078c2ecf20Sopenharmony_ci *
16088c2ecf20Sopenharmony_ci * return
16098c2ecf20Sopenharmony_ci *	0 on success
16108c2ecf20Sopenharmony_ci */
16118c2ecf20Sopenharmony_cistatic int drbg_uninstantiate(struct drbg_state *drbg)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(drbg->jent))
16148c2ecf20Sopenharmony_ci		crypto_free_rng(drbg->jent);
16158c2ecf20Sopenharmony_ci	drbg->jent = NULL;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	if (drbg->d_ops)
16188c2ecf20Sopenharmony_ci		drbg->d_ops->crypto_fini(drbg);
16198c2ecf20Sopenharmony_ci	drbg_dealloc_state(drbg);
16208c2ecf20Sopenharmony_ci	/* no scrubbing of test_data -- this shall survive an uninstantiate */
16218c2ecf20Sopenharmony_ci	return 0;
16228c2ecf20Sopenharmony_ci}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci/*
16258c2ecf20Sopenharmony_ci * Helper function for setting the test data in the DRBG
16268c2ecf20Sopenharmony_ci *
16278c2ecf20Sopenharmony_ci * @drbg DRBG state handle
16288c2ecf20Sopenharmony_ci * @data test data
16298c2ecf20Sopenharmony_ci * @len test data length
16308c2ecf20Sopenharmony_ci */
16318c2ecf20Sopenharmony_cistatic void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
16328c2ecf20Sopenharmony_ci				   const u8 *data, unsigned int len)
16338c2ecf20Sopenharmony_ci{
16348c2ecf20Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	mutex_lock(&drbg->drbg_mutex);
16378c2ecf20Sopenharmony_ci	drbg_string_fill(&drbg->test_data, data, len);
16388c2ecf20Sopenharmony_ci	mutex_unlock(&drbg->drbg_mutex);
16398c2ecf20Sopenharmony_ci}
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci/***************************************************************
16428c2ecf20Sopenharmony_ci * Kernel crypto API cipher invocations requested by DRBG
16438c2ecf20Sopenharmony_ci ***************************************************************/
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
16468c2ecf20Sopenharmony_cistruct sdesc {
16478c2ecf20Sopenharmony_ci	struct shash_desc shash;
16488c2ecf20Sopenharmony_ci	char ctx[];
16498c2ecf20Sopenharmony_ci};
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_cistatic int drbg_init_hash_kernel(struct drbg_state *drbg)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci	struct sdesc *sdesc;
16548c2ecf20Sopenharmony_ci	struct crypto_shash *tfm;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
16578c2ecf20Sopenharmony_ci	if (IS_ERR(tfm)) {
16588c2ecf20Sopenharmony_ci		pr_info("DRBG: could not allocate digest TFM handle: %s\n",
16598c2ecf20Sopenharmony_ci				drbg->core->backend_cra_name);
16608c2ecf20Sopenharmony_ci		return PTR_ERR(tfm);
16618c2ecf20Sopenharmony_ci	}
16628c2ecf20Sopenharmony_ci	BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
16638c2ecf20Sopenharmony_ci	sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
16648c2ecf20Sopenharmony_ci			GFP_KERNEL);
16658c2ecf20Sopenharmony_ci	if (!sdesc) {
16668c2ecf20Sopenharmony_ci		crypto_free_shash(tfm);
16678c2ecf20Sopenharmony_ci		return -ENOMEM;
16688c2ecf20Sopenharmony_ci	}
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	sdesc->shash.tfm = tfm;
16718c2ecf20Sopenharmony_ci	drbg->priv_data = sdesc;
16728c2ecf20Sopenharmony_ci
16738c2ecf20Sopenharmony_ci	return crypto_shash_alignmask(tfm);
16748c2ecf20Sopenharmony_ci}
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_cistatic int drbg_fini_hash_kernel(struct drbg_state *drbg)
16778c2ecf20Sopenharmony_ci{
16788c2ecf20Sopenharmony_ci	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
16798c2ecf20Sopenharmony_ci	if (sdesc) {
16808c2ecf20Sopenharmony_ci		crypto_free_shash(sdesc->shash.tfm);
16818c2ecf20Sopenharmony_ci		kfree_sensitive(sdesc);
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci	drbg->priv_data = NULL;
16848c2ecf20Sopenharmony_ci	return 0;
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_cistatic void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
16888c2ecf20Sopenharmony_ci				  const unsigned char *key)
16898c2ecf20Sopenharmony_ci{
16908c2ecf20Sopenharmony_ci	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
16938c2ecf20Sopenharmony_ci}
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_cistatic int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
16968c2ecf20Sopenharmony_ci			   const struct list_head *in)
16978c2ecf20Sopenharmony_ci{
16988c2ecf20Sopenharmony_ci	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
16998c2ecf20Sopenharmony_ci	struct drbg_string *input = NULL;
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	crypto_shash_init(&sdesc->shash);
17028c2ecf20Sopenharmony_ci	list_for_each_entry(input, in, list)
17038c2ecf20Sopenharmony_ci		crypto_shash_update(&sdesc->shash, input->buf, input->len);
17048c2ecf20Sopenharmony_ci	return crypto_shash_final(&sdesc->shash, outval);
17058c2ecf20Sopenharmony_ci}
17068c2ecf20Sopenharmony_ci#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
17098c2ecf20Sopenharmony_cistatic int drbg_fini_sym_kernel(struct drbg_state *drbg)
17108c2ecf20Sopenharmony_ci{
17118c2ecf20Sopenharmony_ci	struct crypto_cipher *tfm =
17128c2ecf20Sopenharmony_ci		(struct crypto_cipher *)drbg->priv_data;
17138c2ecf20Sopenharmony_ci	if (tfm)
17148c2ecf20Sopenharmony_ci		crypto_free_cipher(tfm);
17158c2ecf20Sopenharmony_ci	drbg->priv_data = NULL;
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	if (drbg->ctr_handle)
17188c2ecf20Sopenharmony_ci		crypto_free_skcipher(drbg->ctr_handle);
17198c2ecf20Sopenharmony_ci	drbg->ctr_handle = NULL;
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	if (drbg->ctr_req)
17228c2ecf20Sopenharmony_ci		skcipher_request_free(drbg->ctr_req);
17238c2ecf20Sopenharmony_ci	drbg->ctr_req = NULL;
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	kfree(drbg->outscratchpadbuf);
17268c2ecf20Sopenharmony_ci	drbg->outscratchpadbuf = NULL;
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci	return 0;
17298c2ecf20Sopenharmony_ci}
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_cistatic int drbg_init_sym_kernel(struct drbg_state *drbg)
17328c2ecf20Sopenharmony_ci{
17338c2ecf20Sopenharmony_ci	struct crypto_cipher *tfm;
17348c2ecf20Sopenharmony_ci	struct crypto_skcipher *sk_tfm;
17358c2ecf20Sopenharmony_ci	struct skcipher_request *req;
17368c2ecf20Sopenharmony_ci	unsigned int alignmask;
17378c2ecf20Sopenharmony_ci	char ctr_name[CRYPTO_MAX_ALG_NAME];
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0);
17408c2ecf20Sopenharmony_ci	if (IS_ERR(tfm)) {
17418c2ecf20Sopenharmony_ci		pr_info("DRBG: could not allocate cipher TFM handle: %s\n",
17428c2ecf20Sopenharmony_ci				drbg->core->backend_cra_name);
17438c2ecf20Sopenharmony_ci		return PTR_ERR(tfm);
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci	BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm));
17468c2ecf20Sopenharmony_ci	drbg->priv_data = tfm;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
17498c2ecf20Sopenharmony_ci	    drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) {
17508c2ecf20Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
17518c2ecf20Sopenharmony_ci		return -EINVAL;
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci	sk_tfm = crypto_alloc_skcipher(ctr_name, 0, 0);
17548c2ecf20Sopenharmony_ci	if (IS_ERR(sk_tfm)) {
17558c2ecf20Sopenharmony_ci		pr_info("DRBG: could not allocate CTR cipher TFM handle: %s\n",
17568c2ecf20Sopenharmony_ci				ctr_name);
17578c2ecf20Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
17588c2ecf20Sopenharmony_ci		return PTR_ERR(sk_tfm);
17598c2ecf20Sopenharmony_ci	}
17608c2ecf20Sopenharmony_ci	drbg->ctr_handle = sk_tfm;
17618c2ecf20Sopenharmony_ci	crypto_init_wait(&drbg->ctr_wait);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	req = skcipher_request_alloc(sk_tfm, GFP_KERNEL);
17648c2ecf20Sopenharmony_ci	if (!req) {
17658c2ecf20Sopenharmony_ci		pr_info("DRBG: could not allocate request queue\n");
17668c2ecf20Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
17678c2ecf20Sopenharmony_ci		return -ENOMEM;
17688c2ecf20Sopenharmony_ci	}
17698c2ecf20Sopenharmony_ci	drbg->ctr_req = req;
17708c2ecf20Sopenharmony_ci	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
17718c2ecf20Sopenharmony_ci						CRYPTO_TFM_REQ_MAY_SLEEP,
17728c2ecf20Sopenharmony_ci					crypto_req_done, &drbg->ctr_wait);
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	alignmask = crypto_skcipher_alignmask(sk_tfm);
17758c2ecf20Sopenharmony_ci	drbg->outscratchpadbuf = kmalloc(DRBG_OUTSCRATCHLEN + alignmask,
17768c2ecf20Sopenharmony_ci					 GFP_KERNEL);
17778c2ecf20Sopenharmony_ci	if (!drbg->outscratchpadbuf) {
17788c2ecf20Sopenharmony_ci		drbg_fini_sym_kernel(drbg);
17798c2ecf20Sopenharmony_ci		return -ENOMEM;
17808c2ecf20Sopenharmony_ci	}
17818c2ecf20Sopenharmony_ci	drbg->outscratchpad = (u8 *)PTR_ALIGN(drbg->outscratchpadbuf,
17828c2ecf20Sopenharmony_ci					      alignmask + 1);
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci	sg_init_table(&drbg->sg_in, 1);
17858c2ecf20Sopenharmony_ci	sg_init_one(&drbg->sg_out, drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci	return alignmask;
17888c2ecf20Sopenharmony_ci}
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_cistatic void drbg_kcapi_symsetkey(struct drbg_state *drbg,
17918c2ecf20Sopenharmony_ci				 const unsigned char *key)
17928c2ecf20Sopenharmony_ci{
17938c2ecf20Sopenharmony_ci	struct crypto_cipher *tfm =
17948c2ecf20Sopenharmony_ci		(struct crypto_cipher *)drbg->priv_data;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	crypto_cipher_setkey(tfm, key, (drbg_keylen(drbg)));
17978c2ecf20Sopenharmony_ci}
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_cistatic int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
18008c2ecf20Sopenharmony_ci			  const struct drbg_string *in)
18018c2ecf20Sopenharmony_ci{
18028c2ecf20Sopenharmony_ci	struct crypto_cipher *tfm =
18038c2ecf20Sopenharmony_ci		(struct crypto_cipher *)drbg->priv_data;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	/* there is only component in *in */
18068c2ecf20Sopenharmony_ci	BUG_ON(in->len < drbg_blocklen(drbg));
18078c2ecf20Sopenharmony_ci	crypto_cipher_encrypt_one(tfm, outval, in->buf);
18088c2ecf20Sopenharmony_ci	return 0;
18098c2ecf20Sopenharmony_ci}
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_cistatic int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
18128c2ecf20Sopenharmony_ci			      u8 *inbuf, u32 inlen,
18138c2ecf20Sopenharmony_ci			      u8 *outbuf, u32 outlen)
18148c2ecf20Sopenharmony_ci{
18158c2ecf20Sopenharmony_ci	struct scatterlist *sg_in = &drbg->sg_in, *sg_out = &drbg->sg_out;
18168c2ecf20Sopenharmony_ci	u32 scratchpad_use = min_t(u32, outlen, DRBG_OUTSCRATCHLEN);
18178c2ecf20Sopenharmony_ci	int ret;
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	if (inbuf) {
18208c2ecf20Sopenharmony_ci		/* Use caller-provided input buffer */
18218c2ecf20Sopenharmony_ci		sg_set_buf(sg_in, inbuf, inlen);
18228c2ecf20Sopenharmony_ci	} else {
18238c2ecf20Sopenharmony_ci		/* Use scratchpad for in-place operation */
18248c2ecf20Sopenharmony_ci		inlen = scratchpad_use;
18258c2ecf20Sopenharmony_ci		memset(drbg->outscratchpad, 0, scratchpad_use);
18268c2ecf20Sopenharmony_ci		sg_set_buf(sg_in, drbg->outscratchpad, scratchpad_use);
18278c2ecf20Sopenharmony_ci	}
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	while (outlen) {
18308c2ecf20Sopenharmony_ci		u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN);
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci		/* Output buffer may not be valid for SGL, use scratchpad */
18338c2ecf20Sopenharmony_ci		skcipher_request_set_crypt(drbg->ctr_req, sg_in, sg_out,
18348c2ecf20Sopenharmony_ci					   cryptlen, drbg->V);
18358c2ecf20Sopenharmony_ci		ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req),
18368c2ecf20Sopenharmony_ci					&drbg->ctr_wait);
18378c2ecf20Sopenharmony_ci		if (ret)
18388c2ecf20Sopenharmony_ci			goto out;
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci		crypto_init_wait(&drbg->ctr_wait);
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci		memcpy(outbuf, drbg->outscratchpad, cryptlen);
18438c2ecf20Sopenharmony_ci		memzero_explicit(drbg->outscratchpad, cryptlen);
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci		outlen -= cryptlen;
18468c2ecf20Sopenharmony_ci		outbuf += cryptlen;
18478c2ecf20Sopenharmony_ci	}
18488c2ecf20Sopenharmony_ci	ret = 0;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ciout:
18518c2ecf20Sopenharmony_ci	return ret;
18528c2ecf20Sopenharmony_ci}
18538c2ecf20Sopenharmony_ci#endif /* CONFIG_CRYPTO_DRBG_CTR */
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci/***************************************************************
18568c2ecf20Sopenharmony_ci * Kernel crypto API interface to register DRBG
18578c2ecf20Sopenharmony_ci ***************************************************************/
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci/*
18608c2ecf20Sopenharmony_ci * Look up the DRBG flags by given kernel crypto API cra_name
18618c2ecf20Sopenharmony_ci * The code uses the drbg_cores definition to do this
18628c2ecf20Sopenharmony_ci *
18638c2ecf20Sopenharmony_ci * @cra_name kernel crypto API cra_name
18648c2ecf20Sopenharmony_ci * @coreref reference to integer which is filled with the pointer to
18658c2ecf20Sopenharmony_ci *  the applicable core
18668c2ecf20Sopenharmony_ci * @pr reference for setting prediction resistance
18678c2ecf20Sopenharmony_ci *
18688c2ecf20Sopenharmony_ci * return: flags
18698c2ecf20Sopenharmony_ci */
18708c2ecf20Sopenharmony_cistatic inline void drbg_convert_tfm_core(const char *cra_driver_name,
18718c2ecf20Sopenharmony_ci					 int *coreref, bool *pr)
18728c2ecf20Sopenharmony_ci{
18738c2ecf20Sopenharmony_ci	int i = 0;
18748c2ecf20Sopenharmony_ci	size_t start = 0;
18758c2ecf20Sopenharmony_ci	int len = 0;
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	*pr = true;
18788c2ecf20Sopenharmony_ci	/* disassemble the names */
18798c2ecf20Sopenharmony_ci	if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
18808c2ecf20Sopenharmony_ci		start = 10;
18818c2ecf20Sopenharmony_ci		*pr = false;
18828c2ecf20Sopenharmony_ci	} else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
18838c2ecf20Sopenharmony_ci		start = 8;
18848c2ecf20Sopenharmony_ci	} else {
18858c2ecf20Sopenharmony_ci		return;
18868c2ecf20Sopenharmony_ci	}
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	/* remove the first part */
18898c2ecf20Sopenharmony_ci	len = strlen(cra_driver_name) - start;
18908c2ecf20Sopenharmony_ci	for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
18918c2ecf20Sopenharmony_ci		if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
18928c2ecf20Sopenharmony_ci			    len)) {
18938c2ecf20Sopenharmony_ci			*coreref = i;
18948c2ecf20Sopenharmony_ci			return;
18958c2ecf20Sopenharmony_ci		}
18968c2ecf20Sopenharmony_ci	}
18978c2ecf20Sopenharmony_ci}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_cistatic int drbg_kcapi_init(struct crypto_tfm *tfm)
19008c2ecf20Sopenharmony_ci{
19018c2ecf20Sopenharmony_ci	struct drbg_state *drbg = crypto_tfm_ctx(tfm);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	mutex_init(&drbg->drbg_mutex);
19048c2ecf20Sopenharmony_ci
19058c2ecf20Sopenharmony_ci	return 0;
19068c2ecf20Sopenharmony_ci}
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_cistatic void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
19098c2ecf20Sopenharmony_ci{
19108c2ecf20Sopenharmony_ci	drbg_uninstantiate(crypto_tfm_ctx(tfm));
19118c2ecf20Sopenharmony_ci}
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci/*
19148c2ecf20Sopenharmony_ci * Generate random numbers invoked by the kernel crypto API:
19158c2ecf20Sopenharmony_ci * The API of the kernel crypto API is extended as follows:
19168c2ecf20Sopenharmony_ci *
19178c2ecf20Sopenharmony_ci * src is additional input supplied to the RNG.
19188c2ecf20Sopenharmony_ci * slen is the length of src.
19198c2ecf20Sopenharmony_ci * dst is the output buffer where random data is to be stored.
19208c2ecf20Sopenharmony_ci * dlen is the length of dst.
19218c2ecf20Sopenharmony_ci */
19228c2ecf20Sopenharmony_cistatic int drbg_kcapi_random(struct crypto_rng *tfm,
19238c2ecf20Sopenharmony_ci			     const u8 *src, unsigned int slen,
19248c2ecf20Sopenharmony_ci			     u8 *dst, unsigned int dlen)
19258c2ecf20Sopenharmony_ci{
19268c2ecf20Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
19278c2ecf20Sopenharmony_ci	struct drbg_string *addtl = NULL;
19288c2ecf20Sopenharmony_ci	struct drbg_string string;
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	if (slen) {
19318c2ecf20Sopenharmony_ci		/* linked list variable is now local to allow modification */
19328c2ecf20Sopenharmony_ci		drbg_string_fill(&string, src, slen);
19338c2ecf20Sopenharmony_ci		addtl = &string;
19348c2ecf20Sopenharmony_ci	}
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	return drbg_generate_long(drbg, dst, dlen, addtl);
19378c2ecf20Sopenharmony_ci}
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci/*
19408c2ecf20Sopenharmony_ci * Seed the DRBG invoked by the kernel crypto API
19418c2ecf20Sopenharmony_ci */
19428c2ecf20Sopenharmony_cistatic int drbg_kcapi_seed(struct crypto_rng *tfm,
19438c2ecf20Sopenharmony_ci			   const u8 *seed, unsigned int slen)
19448c2ecf20Sopenharmony_ci{
19458c2ecf20Sopenharmony_ci	struct drbg_state *drbg = crypto_rng_ctx(tfm);
19468c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
19478c2ecf20Sopenharmony_ci	bool pr = false;
19488c2ecf20Sopenharmony_ci	struct drbg_string string;
19498c2ecf20Sopenharmony_ci	struct drbg_string *seed_string = NULL;
19508c2ecf20Sopenharmony_ci	int coreref = 0;
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
19538c2ecf20Sopenharmony_ci			      &pr);
19548c2ecf20Sopenharmony_ci	if (0 < slen) {
19558c2ecf20Sopenharmony_ci		drbg_string_fill(&string, seed, slen);
19568c2ecf20Sopenharmony_ci		seed_string = &string;
19578c2ecf20Sopenharmony_ci	}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	return drbg_instantiate(drbg, seed_string, coreref, pr);
19608c2ecf20Sopenharmony_ci}
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci/***************************************************************
19638c2ecf20Sopenharmony_ci * Kernel module: code to load the module
19648c2ecf20Sopenharmony_ci ***************************************************************/
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci/*
19678c2ecf20Sopenharmony_ci * Tests as defined in 11.3.2 in addition to the cipher tests: testing
19688c2ecf20Sopenharmony_ci * of the error handling.
19698c2ecf20Sopenharmony_ci *
19708c2ecf20Sopenharmony_ci * Note: testing of failing seed source as defined in 11.3.2 is not applicable
19718c2ecf20Sopenharmony_ci * as seed source of get_random_bytes does not fail.
19728c2ecf20Sopenharmony_ci *
19738c2ecf20Sopenharmony_ci * Note 2: There is no sensible way of testing the reseed counter
19748c2ecf20Sopenharmony_ci * enforcement, so skip it.
19758c2ecf20Sopenharmony_ci */
19768c2ecf20Sopenharmony_cistatic inline int __init drbg_healthcheck_sanity(void)
19778c2ecf20Sopenharmony_ci{
19788c2ecf20Sopenharmony_ci	int len = 0;
19798c2ecf20Sopenharmony_ci#define OUTBUFLEN 16
19808c2ecf20Sopenharmony_ci	unsigned char buf[OUTBUFLEN];
19818c2ecf20Sopenharmony_ci	struct drbg_state *drbg = NULL;
19828c2ecf20Sopenharmony_ci	int ret = -EFAULT;
19838c2ecf20Sopenharmony_ci	int rc = -EFAULT;
19848c2ecf20Sopenharmony_ci	bool pr = false;
19858c2ecf20Sopenharmony_ci	int coreref = 0;
19868c2ecf20Sopenharmony_ci	struct drbg_string addtl;
19878c2ecf20Sopenharmony_ci	size_t max_addtllen, max_request_bytes;
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	/* only perform test in FIPS mode */
19908c2ecf20Sopenharmony_ci	if (!fips_enabled)
19918c2ecf20Sopenharmony_ci		return 0;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DRBG_CTR
19948c2ecf20Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
19958c2ecf20Sopenharmony_ci#elif defined CONFIG_CRYPTO_DRBG_HASH
19968c2ecf20Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
19978c2ecf20Sopenharmony_ci#else
19988c2ecf20Sopenharmony_ci	drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref, &pr);
19998c2ecf20Sopenharmony_ci#endif
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
20028c2ecf20Sopenharmony_ci	if (!drbg)
20038c2ecf20Sopenharmony_ci		return -ENOMEM;
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci	mutex_init(&drbg->drbg_mutex);
20068c2ecf20Sopenharmony_ci	drbg->core = &drbg_cores[coreref];
20078c2ecf20Sopenharmony_ci	drbg->reseed_threshold = drbg_max_requests(drbg);
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	/*
20108c2ecf20Sopenharmony_ci	 * if the following tests fail, it is likely that there is a buffer
20118c2ecf20Sopenharmony_ci	 * overflow as buf is much smaller than the requested or provided
20128c2ecf20Sopenharmony_ci	 * string lengths -- in case the error handling does not succeed
20138c2ecf20Sopenharmony_ci	 * we may get an OOPS. And we want to get an OOPS as this is a
20148c2ecf20Sopenharmony_ci	 * grave bug.
20158c2ecf20Sopenharmony_ci	 */
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	max_addtllen = drbg_max_addtl(drbg);
20188c2ecf20Sopenharmony_ci	max_request_bytes = drbg_max_request_bytes(drbg);
20198c2ecf20Sopenharmony_ci	drbg_string_fill(&addtl, buf, max_addtllen + 1);
20208c2ecf20Sopenharmony_ci	/* overflow addtllen with additonal info string */
20218c2ecf20Sopenharmony_ci	len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
20228c2ecf20Sopenharmony_ci	BUG_ON(0 < len);
20238c2ecf20Sopenharmony_ci	/* overflow max_bits */
20248c2ecf20Sopenharmony_ci	len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
20258c2ecf20Sopenharmony_ci	BUG_ON(0 < len);
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	/* overflow max addtllen with personalization string */
20288c2ecf20Sopenharmony_ci	ret = drbg_seed(drbg, &addtl, false);
20298c2ecf20Sopenharmony_ci	BUG_ON(0 == ret);
20308c2ecf20Sopenharmony_ci	/* all tests passed */
20318c2ecf20Sopenharmony_ci	rc = 0;
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	pr_devel("DRBG: Sanity tests for failure code paths successfully "
20348c2ecf20Sopenharmony_ci		 "completed\n");
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	kfree(drbg);
20378c2ecf20Sopenharmony_ci	return rc;
20388c2ecf20Sopenharmony_ci}
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_cistatic struct rng_alg drbg_algs[22];
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci/*
20438c2ecf20Sopenharmony_ci * Fill the array drbg_algs used to register the different DRBGs
20448c2ecf20Sopenharmony_ci * with the kernel crypto API. To fill the array, the information
20458c2ecf20Sopenharmony_ci * from drbg_cores[] is used.
20468c2ecf20Sopenharmony_ci */
20478c2ecf20Sopenharmony_cistatic inline void __init drbg_fill_array(struct rng_alg *alg,
20488c2ecf20Sopenharmony_ci					  const struct drbg_core *core, int pr)
20498c2ecf20Sopenharmony_ci{
20508c2ecf20Sopenharmony_ci	int pos = 0;
20518c2ecf20Sopenharmony_ci	static int priority = 200;
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	memcpy(alg->base.cra_name, "stdrng", 6);
20548c2ecf20Sopenharmony_ci	if (pr) {
20558c2ecf20Sopenharmony_ci		memcpy(alg->base.cra_driver_name, "drbg_pr_", 8);
20568c2ecf20Sopenharmony_ci		pos = 8;
20578c2ecf20Sopenharmony_ci	} else {
20588c2ecf20Sopenharmony_ci		memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10);
20598c2ecf20Sopenharmony_ci		pos = 10;
20608c2ecf20Sopenharmony_ci	}
20618c2ecf20Sopenharmony_ci	memcpy(alg->base.cra_driver_name + pos, core->cra_name,
20628c2ecf20Sopenharmony_ci	       strlen(core->cra_name));
20638c2ecf20Sopenharmony_ci
20648c2ecf20Sopenharmony_ci	alg->base.cra_priority = priority;
20658c2ecf20Sopenharmony_ci	priority++;
20668c2ecf20Sopenharmony_ci	/*
20678c2ecf20Sopenharmony_ci	 * If FIPS mode enabled, the selected DRBG shall have the
20688c2ecf20Sopenharmony_ci	 * highest cra_priority over other stdrng instances to ensure
20698c2ecf20Sopenharmony_ci	 * it is selected.
20708c2ecf20Sopenharmony_ci	 */
20718c2ecf20Sopenharmony_ci	if (fips_enabled)
20728c2ecf20Sopenharmony_ci		alg->base.cra_priority += 200;
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	alg->base.cra_ctxsize 	= sizeof(struct drbg_state);
20758c2ecf20Sopenharmony_ci	alg->base.cra_module	= THIS_MODULE;
20768c2ecf20Sopenharmony_ci	alg->base.cra_init	= drbg_kcapi_init;
20778c2ecf20Sopenharmony_ci	alg->base.cra_exit	= drbg_kcapi_cleanup;
20788c2ecf20Sopenharmony_ci	alg->generate		= drbg_kcapi_random;
20798c2ecf20Sopenharmony_ci	alg->seed		= drbg_kcapi_seed;
20808c2ecf20Sopenharmony_ci	alg->set_ent		= drbg_kcapi_set_entropy;
20818c2ecf20Sopenharmony_ci	alg->seedsize		= 0;
20828c2ecf20Sopenharmony_ci}
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_cistatic int __init drbg_init(void)
20858c2ecf20Sopenharmony_ci{
20868c2ecf20Sopenharmony_ci	unsigned int i = 0; /* pointer to drbg_algs */
20878c2ecf20Sopenharmony_ci	unsigned int j = 0; /* pointer to drbg_cores */
20888c2ecf20Sopenharmony_ci	int ret;
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci	ret = drbg_healthcheck_sanity();
20918c2ecf20Sopenharmony_ci	if (ret)
20928c2ecf20Sopenharmony_ci		return ret;
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
20958c2ecf20Sopenharmony_ci		pr_info("DRBG: Cannot register all DRBG types"
20968c2ecf20Sopenharmony_ci			"(slots needed: %zu, slots available: %zu)\n",
20978c2ecf20Sopenharmony_ci			ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
20988c2ecf20Sopenharmony_ci		return -EFAULT;
20998c2ecf20Sopenharmony_ci	}
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	/*
21028c2ecf20Sopenharmony_ci	 * each DRBG definition can be used with PR and without PR, thus
21038c2ecf20Sopenharmony_ci	 * we instantiate each DRBG in drbg_cores[] twice.
21048c2ecf20Sopenharmony_ci	 *
21058c2ecf20Sopenharmony_ci	 * As the order of placing them into the drbg_algs array matters
21068c2ecf20Sopenharmony_ci	 * (the later DRBGs receive a higher cra_priority) we register the
21078c2ecf20Sopenharmony_ci	 * prediction resistance DRBGs first as the should not be too
21088c2ecf20Sopenharmony_ci	 * interesting.
21098c2ecf20Sopenharmony_ci	 */
21108c2ecf20Sopenharmony_ci	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
21118c2ecf20Sopenharmony_ci		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
21128c2ecf20Sopenharmony_ci	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
21138c2ecf20Sopenharmony_ci		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
21148c2ecf20Sopenharmony_ci	return crypto_register_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
21158c2ecf20Sopenharmony_ci}
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_cistatic void __exit drbg_exit(void)
21188c2ecf20Sopenharmony_ci{
21198c2ecf20Sopenharmony_ci	crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
21208c2ecf20Sopenharmony_ci}
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_cisubsys_initcall(drbg_init);
21238c2ecf20Sopenharmony_cimodule_exit(drbg_exit);
21248c2ecf20Sopenharmony_ci#ifndef CRYPTO_DRBG_HASH_STRING
21258c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_HASH_STRING ""
21268c2ecf20Sopenharmony_ci#endif
21278c2ecf20Sopenharmony_ci#ifndef CRYPTO_DRBG_HMAC_STRING
21288c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_HMAC_STRING ""
21298c2ecf20Sopenharmony_ci#endif
21308c2ecf20Sopenharmony_ci#ifndef CRYPTO_DRBG_CTR_STRING
21318c2ecf20Sopenharmony_ci#define CRYPTO_DRBG_CTR_STRING ""
21328c2ecf20Sopenharmony_ci#endif
21338c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
21348c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
21358c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
21368c2ecf20Sopenharmony_ci		   "using following cores: "
21378c2ecf20Sopenharmony_ci		   CRYPTO_DRBG_HASH_STRING
21388c2ecf20Sopenharmony_ci		   CRYPTO_DRBG_HMAC_STRING
21398c2ecf20Sopenharmony_ci		   CRYPTO_DRBG_CTR_STRING);
21408c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("stdrng");
2141