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