diff options
| author | Eric Biggers <ebiggers@kernel.org> | 2026-05-31 12:17:37 -0700 |
|---|---|---|
| committer | Herbert Xu <herbert@gondor.apana.org.au> | 2026-06-11 14:03:13 +0800 |
| commit | 5f1d444e084ce3e4619e38c45a8cc29e6fffb2bf (patch) | |
| tree | 3fb4866d0e455e66335bb5350e62df2c39c5c83c /crypto | |
| parent | 2dd67774228930ccf6441e5628996021f410c4e0 (diff) | |
| download | linux-2.6-5f1d444e084ce3e4619e38c45a8cc29e6fffb2bf.tar.gz linux-2.6-5f1d444e084ce3e4619e38c45a8cc29e6fffb2bf.zip | |
crypto: xilinx-trng - Replace crypto_drbg_ctr_df() with HMAC-SHA512
This code is just trying to condition 48 bytes of random data. This can
be done easily using HKDF-SHA512-Extract, saving 300 lines of code.
This commit also fixes forward security (in this particular case) by
clearing the entropy from memory after it's used.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
| -rw-r--r-- | crypto/Kconfig | 5 | ||||
| -rw-r--r-- | crypto/Makefile | 2 | ||||
| -rw-r--r-- | crypto/df_sp80090a.c | 222 |
3 files changed, 0 insertions, 229 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index b5c5a1e04435..c3d7a20d5cb1 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1246,11 +1246,6 @@ config CRYPTO_KDF800108_CTR select CRYPTO_HMAC select CRYPTO_SHA256 -config CRYPTO_DF80090A - tristate - select CRYPTO_AES - select CRYPTO_CTR - endmenu menu "Userspace interface (deprecated)" diff --git a/crypto/Makefile b/crypto/Makefile index c73f4d51d036..f98f57c7a49f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -208,6 +208,4 @@ obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o # obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o -obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o - obj-$(CONFIG_CRYPTO_KRB5) += krb5/ diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c deleted file mode 100644 index 90e1973ee40c..000000000000 --- a/crypto/df_sp80090a.c +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* - * NIST SP800-90A DRBG derivation function - * - * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de> - */ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/string.h> -#include <linux/unaligned.h> -#include <crypto/aes.h> -#include <crypto/df_sp80090a.h> - -static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval, - const struct drbg_string *in, u8 blocklen_bytes) -{ - /* there is only component in *in */ - BUG_ON(in->len < blocklen_bytes); - aes_encrypt(aeskey, outval, in->buf); -} - -/* BCC function for CTR DRBG as defined in 10.4.3 */ - -static void drbg_ctr_bcc(struct aes_enckey *aeskey, - unsigned char *out, const unsigned char *key, - struct list_head *in, - u8 blocklen_bytes, - u8 keylen) -{ - struct drbg_string *curr = NULL; - struct drbg_string data; - short cnt = 0; - - drbg_string_fill(&data, out, blocklen_bytes); - - /* 10.4.3 step 2 / 4 */ - aes_prepareenckey(aeskey, key, keylen); - list_for_each_entry(curr, in, list) { - const unsigned char *pos = curr->buf; - size_t len = curr->len; - /* 10.4.3 step 4.1 */ - while (len) { - /* 10.4.3 step 4.2 */ - if (blocklen_bytes == cnt) { - cnt = 0; - drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); - } - out[cnt] ^= *pos; - pos++; - cnt++; - len--; - } - } - /* 10.4.3 step 4.2 for last block */ - if (cnt) - drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); -} - -/* - * scratchpad usage: drbg_ctr_update is interlinked with crypto_drbg_ctr_df - * (and drbg_ctr_bcc, but this function does not need any temporary buffers), - * the scratchpad is used as follows: - * drbg_ctr_update: - * temp - * start: drbg->scratchpad - * length: drbg_statelen(drbg) + drbg_blocklen(drbg) - * note: the cipher writing into this variable works - * blocklen-wise. Now, when the statelen is not a multiple - * of blocklen, the generateion loop below "spills over" - * by at most blocklen. Thus, we need to give sufficient - * memory. - * df_data - * start: drbg->scratchpad + - * drbg_statelen(drbg) + drbg_blocklen(drbg) - * length: drbg_statelen(drbg) - * - * crypto_drbg_ctr_df: - * pad - * start: df_data + drbg_statelen(drbg) - * length: drbg_blocklen(drbg) - * iv - * start: pad + drbg_blocklen(drbg) - * length: drbg_blocklen(drbg) - * temp - * start: iv + drbg_blocklen(drbg) - * length: drbg_satelen(drbg) + drbg_blocklen(drbg) - * note: temp is the buffer that the BCC function operates - * on. BCC operates blockwise. drbg_statelen(drbg) - * is sufficient when the DRBG state length is a multiple - * of the block size. For AES192 (and maybe other ciphers) - * this is not correct and the length for temp is - * insufficient (yes, that also means for such ciphers, - * the final output of all BCC rounds are truncated). - * Therefore, add drbg_blocklen(drbg) to cover all - * possibilities. - * refer to crypto_drbg_ctr_df_datalen() to get required length - */ - -/* Derivation Function for CTR DRBG as defined in 10.4.2 */ -int crypto_drbg_ctr_df(struct aes_enckey *aeskey, - unsigned char *df_data, size_t bytes_to_return, - struct list_head *seedlist, - u8 blocklen_bytes, - u8 statelen) -{ - unsigned char L_N[8]; - /* S3 is input */ - struct drbg_string S1, S2, S4, cipherin; - LIST_HEAD(bcc_list); - unsigned char *pad = df_data + statelen; - unsigned char *iv = pad + blocklen_bytes; - unsigned char *temp = iv + blocklen_bytes; - size_t padlen = 0; - unsigned int templen = 0; - /* 10.4.2 step 7 */ - unsigned int i = 0; - /* 10.4.2 step 8 */ - const unsigned char *K = (unsigned char *) - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; - unsigned char *X; - size_t generated_len = 0; - size_t inputlen = 0; - struct drbg_string *seed = NULL; - u8 keylen; - - memset(pad, 0, blocklen_bytes); - memset(iv, 0, blocklen_bytes); - keylen = statelen - blocklen_bytes; - /* 10.4.2 step 1 is implicit as we work byte-wise */ - - /* 10.4.2 step 2 */ - if ((512 / 8) < bytes_to_return) - return -EINVAL; - - /* 10.4.2 step 2 -- calculate the entire length of all input data */ - list_for_each_entry(seed, seedlist, list) - inputlen += seed->len; - put_unaligned_be32(inputlen, &L_N[0]); - - /* 10.4.2 step 3 */ - put_unaligned_be32(bytes_to_return, &L_N[4]); - - /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */ - padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes); - /* wrap the padlen appropriately */ - if (padlen) - padlen = blocklen_bytes - padlen; - /* - * pad / padlen contains the 0x80 byte and the following zero bytes. - * As the calculated padlen value only covers the number of zero - * bytes, this value has to be incremented by one for the 0x80 byte. - */ - padlen++; - pad[0] = 0x80; - - /* 10.4.2 step 4 -- first fill the linked list and then order it */ - drbg_string_fill(&S1, iv, blocklen_bytes); - list_add_tail(&S1.list, &bcc_list); - drbg_string_fill(&S2, L_N, sizeof(L_N)); - list_add_tail(&S2.list, &bcc_list); - list_splice_tail(seedlist, &bcc_list); - drbg_string_fill(&S4, pad, padlen); - list_add_tail(&S4.list, &bcc_list); - - /* 10.4.2 step 9 */ - while (templen < (keylen + (blocklen_bytes))) { - /* - * 10.4.2 step 9.1 - the padding is implicit as the buffer - * holds zeros after allocation -- even the increment of i - * is irrelevant as the increment remains within length of i - */ - put_unaligned_be32(i, iv); - /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ - drbg_ctr_bcc(aeskey, temp + templen, K, &bcc_list, - blocklen_bytes, keylen); - /* 10.4.2 step 9.3 */ - i++; - templen += blocklen_bytes; - } - - /* 10.4.2 step 11 */ - X = temp + (keylen); - drbg_string_fill(&cipherin, X, blocklen_bytes); - - /* 10.4.2 step 12: overwriting of outval is implemented in next step */ - - /* 10.4.2 step 13 */ - aes_prepareenckey(aeskey, temp, keylen); - while (generated_len < bytes_to_return) { - short blocklen = 0; - /* - * 10.4.2 step 13.1: the truncation of the key length is - * implicit as the key is only drbg_blocklen in size based on - * the implementation of the cipher function callback - */ - drbg_kcapi_sym(aeskey, X, &cipherin, blocklen_bytes); - blocklen = (blocklen_bytes < - (bytes_to_return - generated_len)) ? - blocklen_bytes : - (bytes_to_return - generated_len); - /* 10.4.2 step 13.2 and 14 */ - memcpy(df_data + generated_len, X, blocklen); - generated_len += blocklen; - } - - memset(iv, 0, blocklen_bytes); - memset(temp, 0, statelen + blocklen_bytes); - memset(pad, 0, blocklen_bytes); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_drbg_ctr_df); - -MODULE_IMPORT_NS("CRYPTO_INTERNAL"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); -MODULE_DESCRIPTION("Derivation Function conformant to SP800-90A"); |
