Hi,
the following set of patches implements the deterministic random bit generator
(DRBG) specified by SP800-90A.
The DRBG implementation offers the following:
* All three DRBG types are implemented with a derivation function.
* All DRBG types are available with and without prediction resistance.
* All SHA types of SHA-1, SHA-256, SHA-384, SHA-512 are available
for the HMAC and Hash DRBGs.
* All AES types of AES-128, AES-192 and AES-256 are available for the
CTR DRBG.
* A self test is implemented with drbg_healthcheck().
* The FIPS 140-2 continuous self test is implemented.
* Additional cipher primitives, such as Serpent or Twofish, can be
added to the DRBG without changing the implementation. The only
change necessary is to the DRBG definition given in the cores[]
array.
As defined in SP800-131A, the ANSI X9.31 DRNG is to be sunset by the end of
this year for official uses, including FIPS 140-2 compliance.
Additional tests are available at [1].
[1] http://www.chronox.de/drbg.html
Stephan Mueller (6):
SP800-90A Deterministic Random Bit Generator
header file for DRBG
DRBG kernel configuration options
compile the DRBG code
DRBG testmgr test vectors
Add DRBG test code to testmgr
crypto/Kconfig | 36 +-
crypto/Makefile | 1 +
crypto/drbg.c | 1941 +++++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.c | 269 +++++++
crypto/testmgr.h | 877 ++++++++++++++++++++++
include/crypto/drbg.h | 340 +++++++++
6 files changed, 3463 insertions(+), 1 deletion(-)
create mode 100644 crypto/drbg.c
create mode 100644 include/crypto/drbg.h
--
1.8.5.3
,
Ciao
Stephan
--
| Cui bono? |
Signed-off-by: Stephan Mueller <[email protected]>
diff --git a/crypto/Makefile b/crypto/Makefile
index b29402a..0d63373 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_CRYPTO_842) += 842.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
+obj-$(CONFIG_CRYTPO_DRBG) += drbg.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
--
1.8.5.3
The different DRBG types of CTR, Hash, HMAC can be enabled or disabled
at compile time. At least one DRBG type shall be selected.
The default is the HMAC DRBG as its code base is smallest.
Signed-off-by: Stephan Mueller <[email protected]>
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7bcb70d..2cdf9c6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -23,7 +23,7 @@ comment "Crypto core or helper"
config CRYPTO_FIPS
bool "FIPS 200 compliance"
- depends on CRYPTO_ANSI_CPRNG && !CRYPTO_MANAGER_DISABLE_TESTS
+ depends on (CRYPTO_ANSI_CPRNG || CRYTPO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
help
This options enables the fips boot option which is
required if you want to system to operate in a FIPS 200
@@ -1380,6 +1380,40 @@ config CRYPTO_ANSI_CPRNG
ANSI X9.31 A.2.4. Note that this option must be enabled if
CRYPTO_FIPS is selected
+menuconfig CRYTPO_DRBG
+ tristate "NIST SP800-90A DRBG"
+ depends on CRYPTO
+ select CRYPTO_RNG
+ help
+ NIST SP800-90A compliant DRBG. In the following submenu, one or
+ more of the DRBG types must be selected.
+
+if CRYTPO_DRBG
+
+config CRYPTO_DRBG_HMAC
+ bool "Enable HMAC DRBG"
+ default y
+ depends on CRYTPO_DRBG
+ select CRYPTO_HMAC
+ help
+ Enable the HMAC DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_HASH
+ bool "Enable Hash DRBG"
+ depends on CRYTPO_DRBG
+ select CRYPTO_HASH
+ help
+ Enable the Hash DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_CTR
+ bool "Enable CTR DRBG"
+ depends on CRYTPO_DRBG
+ select CRYPTO_AES
+ help
+ Enable the CTR DRBG variant as defined in NIST SP800-90A.
+
+endif #CRYTPO_DRBG
+
config CRYPTO_USER_API
tristate
--
1.8.5.3
This is a clean-room implementation of the DRBG defined in SP800-90A.
All three viable DRBGs defined in the standard are implemented:
* HMAC
* Hash
* CTR
Signed-off-by: Stephan Mueller <[email protected]>
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..5308cce
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1941 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char personalization = "some-string";
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl = "some-string";
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng,
+ * &data, DATALEN,
+ * &addtl, strlen(addtl));
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+static int drbg_kcapi_hmac(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in);
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+const struct drbg_core cores[] =
+{
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASHSHA1,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cipher_fn = drbg_kcapi_hash,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASHSHA256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cipher_fn = drbg_kcapi_hash,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASHSHA384,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cipher_fn = drbg_kcapi_hash,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASHSHA512,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cipher_fn = drbg_kcapi_hash,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMACSHA1,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cipher_fn = drbg_kcapi_hmac,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMACSHA256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cipher_fn = drbg_kcapi_hmac,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMACSHA384,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cipher_fn = drbg_kcapi_hmac,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMACSHA512,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cipher_fn = drbg_kcapi_hmac,
+ .init_lib = drbg_init_hash_kernel,
+ .fini_lib = drbg_fini_hash_kernel,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTRAES128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cipher_fn = drbg_kcapi_sym,
+ .init_lib = drbg_init_sym_kernel,
+ .fini_lib = drbg_fini_sym_kernel,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTRAES192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cipher_fn = drbg_kcapi_sym,
+ .init_lib = drbg_init_sym_kernel,
+ .fini_lib = drbg_fini_sym_kernel,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTRAES256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cipher_fn = drbg_kcapi_sym,
+ .init_lib = drbg_init_sym_kernel,
+ .fini_lib = drbg_fini_sym_kernel,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * flags: DRBG flags reference
+ *
+ * Return: normalized strength value or 0 on error
+ */
+static unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch(flags & DRBG_CIPHER_MASK) {
+ case DRBG_CTRAES128:
+ case DRBG_CTRSERPENT128:
+ case DRBG_CTRTWOFISH128:
+ case DRBG_HASHSHA1:
+ case DRBG_HMACSHA1:
+ return 128;
+ case DRBG_CTRAES192:
+ case DRBG_CTRSERPENT192:
+ case DRBG_CTRTWOFISH192:
+ return 192;
+ case DRBG_CTRAES256:
+ case DRBG_CTRSERPENT256:
+ case DRBG_CTRTWOFISH256:
+ case DRBG_HASHSHA256:
+ case DRBG_HASHSHA384:
+ case DRBG_HASHSHA512:
+ case DRBG_HMACSHA256:
+ case DRBG_HMACSHA384:
+ case DRBG_HMACSHA512:
+ return 256;
+ default:
+ return 0;
+ }
+}
+
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val, size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while(len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while(len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, unsigned char *key,
+ struct drbg_conc *in)
+{
+ int ret = -EFAULT;
+ struct drbg_conc *curr = in;
+ size_t inpos = curr->len;
+ unsigned char *pos = curr->in;
+ struct drbg_conc data;
+
+ DRBG_CLEAR_CONC(data);
+ data.in = out;
+ data.len = DRBG_BLOCKLEN(drbg);
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, DRBG_BLOCKLEN(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while(inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for(cnt = 0; cnt < DRBG_BLOCKLEN(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if(0 == inpos) {
+ curr = curr->next;
+ if(NULL != curr) {
+ pos = curr->in;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg->core->cipher_fn(drbg, key, out, &data);
+ if(ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *out, size_t bytes_to_return,
+ struct drbg_conc *input)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_conc S1, S2, S4;
+ unsigned char temp[DRBG_CTR_BLK], pad[DRBG_CTR_BLK], IV[DRBG_CTR_BLK];
+ size_t padlen = 1; /* already reserve space for 0x80 */
+ int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 - truncation happens in ->cipher_fn which uses only
+ * DRBG_BLOCKLEN bits of key */
+ 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;
+ struct drbg_conc cipherin;
+ size_t generated_len = 0;
+ size_t inputlen = 0;
+ struct drbg_conc *tempconc = input;
+
+ DRBG_CLEAR_CTR_BLK(pad);
+ DRBG_CLEAR_CTR_BLK(temp);
+ DRBG_CLEAR_CTR_BLK(IV);
+ DRBG_CLEAR_CONC(S1);
+ DRBG_CLEAR_CONC(S2);
+ DRBG_CLEAR_CONC(S4);
+
+ /* 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*/
+ for(; NULL != tempconc; tempconc = tempconc->next)
+ inputlen += tempconc->len;
+
+ drbg_int2byte(&L_N[0], inputlen, 4);
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ while(0 != ((8 + inputlen + padlen) % (DRBG_BLOCKLEN(drbg))))
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first arrange the linked list and then fill it */
+ S1.next = &S2;
+ S2.next = input;
+ /* splice in input between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempconc = input;
+ for(; NULL != tempconc; tempconc = tempconc->next)
+ if(NULL == tempconc->next)
+ break;
+ tempconc->next = &S4;
+
+ S1.in = IV;
+ S1.len = DRBG_BLOCKLEN(drbg);
+ S2.in = L_N;
+ S2.len = 8;
+ S4.in = pad;
+ S4.len = padlen;
+
+ /* 10.4.2 step 9 */
+ while(templen < (DRBG_KEYLEN(drbg) + (DRBG_BLOCKLEN(drbg)))) {
+ /* 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 */
+ drbg_int2byte(IV, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if(ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += DRBG_BLOCKLEN(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (DRBG_KEYLEN(drbg));
+ cipherin.in = X; cipherin.len = DRBG_BLOCKLEN(drbg);
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg->core->cipher_fn(drbg, temp, X, &cipherin);
+ if(ret)
+ goto out;
+ blocklen = (DRBG_BLOCKLEN(drbg) <
+ (bytes_to_return - generated_len)) ?
+ DRBG_BLOCKLEN(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(out + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ DRBG_CLEAR_CTR_BLK(IV);
+ DRBG_CLEAR_CTR_BLK(temp);
+ DRBG_CLEAR_CTR_BLK(pad);
+ return ret;
+}
+
+static int drbg_ctr_update_state(struct drbg_state *drbg,
+ struct drbg_conc *prov_data,
+ int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char temp[DRBG_CTR_BLK], df_data[DRBG_CTR_BLK];
+ unsigned char *temp_p, *df_data_p; /* not malloced */
+ int len = 0;
+ struct drbg_conc cipherin;
+
+ DRBG_CLEAR_CTR_BLK(temp);
+ DRBG_CLEAR_CTR_BLK(df_data);
+ DRBG_CLEAR_CONC(cipherin);
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if(0 < prov_data->len) {
+ ret = drbg_ctr_df(drbg, df_data, DRBG_STATELEN(drbg),
+ prov_data);
+ if(ret)
+ goto out;
+ }
+
+ cipherin.in = drbg->V; cipherin.len = DRBG_BLOCKLEN(drbg);
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while(len < (DRBG_STATELEN(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, DRBG_BLOCKLEN(drbg),
+ (unsigned char *) "\1", 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg->core->cipher_fn(drbg, drbg->C, temp + len,
+ &cipherin);
+ if(ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += DRBG_BLOCKLEN(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for(len = 0; len < DRBG_STATELEN(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, DRBG_KEYLEN(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + DRBG_KEYLEN(drbg), DRBG_BLOCKLEN(drbg));
+ ret = 0;
+
+out:
+ DRBG_CLEAR_CTR_BLK(df_data);
+ DRBG_CLEAR_CTR_BLK(temp);
+ return ret;
+}
+
+static int drbg_ctr_process_addtl(struct drbg_state *drbg,
+ unsigned char *addtl_input, size_t addtllen)
+{
+ struct drbg_conc addtl;
+ DRBG_CLEAR_CONC(addtl);
+ if(0 == addtllen)
+ return 0;
+ /* 10.2.1.5.2 step 2 */
+ addtl.in = addtl_input;
+ addtl.len = addtllen;
+ return drbg_ctr_update_state(drbg, &addtl, 1);
+}
+
+static int drbg_ctr_preprocess_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst,
+ short *length)
+{
+ memset(drbg->scratchpad, 0, DRBG_BLOCKLEN(drbg));
+ *src = drbg->V;
+ *dst = (unsigned char *)drbg->scratchpad;
+ *length = DRBG_BLOCKLEN(drbg);
+
+ drbg_add_buf(*src, DRBG_BLOCKLEN(drbg),
+ (unsigned char *) "\1", 1);
+
+ return 0;
+}
+
+static void drbg_ctr_postprocess_extract(struct drbg_state *drbg,
+ unsigned char *src,
+ unsigned char *dst, int notlast)
+{
+ /* 10.2.1.5.2 step 4.1 */
+ if(notlast)
+ drbg_add_buf(src, DRBG_BLOCKLEN(drbg),
+ (unsigned char *) "\1", 1);
+}
+
+static void drbg_ctr_cleanup_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst)
+{
+ memset(drbg->scratchpad, 0, DRBG_BLOCKLEN(drbg));
+}
+
+static int drbg_ctr_newstate_postgen(struct drbg_state *drbg,
+ unsigned char *addtl_input,
+ size_t addtllen)
+{
+ struct drbg_conc addtl;
+ DRBG_CLEAR_CONC(addtl);
+ addtl.in = addtl_input;
+ addtl.len = addtllen;
+ /* 10.1.2.5 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here*/
+ return drbg_ctr_update_state(drbg, &addtl, 1);
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .process_addtl = drbg_ctr_process_addtl,
+ .preprocess_extract = drbg_ctr_preprocess_extract,
+ .postprocess_extract = drbg_ctr_postprocess_extract,
+ .cleanup_extract = drbg_ctr_cleanup_extract,
+ .newstate_postgen = drbg_ctr_newstate_postgen,
+ .update_state = drbg_ctr_update_state,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+static int drbg_hmac_update_state(struct drbg_state *drbg,
+ struct drbg_conc *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_conc seed1, seed2, cipherin;
+
+ DRBG_CLEAR_CONC(seed1);
+ DRBG_CLEAR_CONC(seed2);
+ DRBG_CLEAR_CONC(cipherin);
+
+ if(!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, DRBG_STATELEN(drbg));
+ memset(drbg->V, 1, DRBG_STATELEN(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ seed1.next = &seed2;
+ seed2.next = seed;
+ seed1.in = drbg->V;
+ seed1.len = DRBG_STATELEN(drbg);
+
+ cipherin.in = drbg->V;
+ cipherin.len = DRBG_STATELEN(drbg);
+ /* we execute two rounds of V/K massaging */
+ for(i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = '\0';
+ if(1 == i)
+ prefix = '\1';
+
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.in = &prefix;
+ seed2.len = 1;
+ ret = drbg->core->cipher_fn(drbg, drbg->C, drbg->C, &seed1);
+ if(ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg->core->cipher_fn(drbg, drbg->C, drbg->V, &cipherin);
+ if(ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if(0 == seed->len)
+ return ret;
+ }
+ ret = 0;
+
+ return ret;
+}
+
+static int drbg_hmac_process_addtl(struct drbg_state *drbg,
+ unsigned char *addtl_input, size_t addtllen)
+{
+ struct drbg_conc addtl;
+ DRBG_CLEAR_CONC(addtl);
+ if(0 == addtllen)
+ return 0;
+ addtl.in = addtl_input;
+ addtl.len = addtllen;
+ /* 10.1.2.5 step 2 */
+ return drbg_hmac_update_state(drbg, &addtl, 1);
+}
+
+static int drbg_hmac_preprocess_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst,
+ short *length)
+{
+ *src = drbg->V;
+ *dst = drbg->V;
+ *length = DRBG_STATELEN(drbg);
+ return 0;
+}
+static void drbg_hmac_postprocess_extract(struct drbg_state *drbg,
+ unsigned char *src,
+ unsigned char *dst, int notlast)
+{
+ /* nothing needed */
+}
+
+static void drbg_hmac_cleanup_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst)
+{
+ /* nothing needed */
+}
+
+static int drbg_hmac_newstate_postgen(struct drbg_state *drbg,
+ unsigned char *addtl_input,
+ size_t addtllen)
+{
+ struct drbg_conc addtl;
+ DRBG_CLEAR_CONC(addtl);
+ addtl.in = addtl_input;
+ addtl.len = addtllen;
+ /* 10.1.2.5 step 6 */
+ return drbg_hmac_update_state(drbg, &addtl, 1);
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .process_addtl = drbg_hmac_process_addtl,
+ .preprocess_extract = drbg_hmac_preprocess_extract,
+ .postprocess_extract = drbg_hmac_postprocess_extract,
+ .cleanup_extract = drbg_hmac_cleanup_extract,
+ .newstate_postgen = drbg_hmac_newstate_postgen,
+ .update_state = drbg_hmac_update_state,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_conc *entropy)
+{
+ int ret = 0;
+ /* 10.1.1.4 step 1 */
+ size_t len = 0;
+ unsigned char tmp[DRBG_HASH_BLK], input[5];
+ struct drbg_conc data1;
+
+ DRBG_CLEAR_HASH_BLK(tmp);
+ DRBG_CLEAR_CONC(data1);
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ data1.next = entropy;
+ data1.in = input;
+ data1.len = 5;
+
+ /* 10.4.1 step 4 */
+ while(len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg->core->cipher_fn(drbg, NULL, tmp, &data1);
+ if(ret) {
+ memset(outval, 0, outlen);
+ goto out;
+ }
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (DRBG_BLOCKLEN(drbg) < (outlen - len)) ?
+ DRBG_BLOCKLEN(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ DRBG_CLEAR_HASH_BLK(tmp);
+ return ret;
+}
+
+static int drbg_hash_update_state(struct drbg_state *drbg,
+ struct drbg_conc *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_conc data1, data2;
+ unsigned char V[DRBG_HASH_BLK];
+
+ DRBG_CLEAR_HASH_BLK(V);
+ DRBG_CLEAR_CONC(data1);
+ DRBG_CLEAR_CONC(data2);
+
+ if(reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, DRBG_STATELEN(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ data1.in = (unsigned char *)"\1";
+ data1.len = 1;
+ data2.in = V;
+ data2.len = DRBG_STATELEN(drbg);
+ } else {
+ data1.in = seed->in;
+ data1.len = seed->len;
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, DRBG_STATELEN(drbg), &data1);
+ if(ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ data1.next = &data2;
+ data2.next = NULL;
+ data1.in = (unsigned char *)"\0";
+ data1.len = 1;
+ data2.in = drbg->V;
+ data2.len = DRBG_STATELEN(drbg);
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, DRBG_STATELEN(drbg), &data1);
+
+out:
+ DRBG_CLEAR_HASH_BLK(V);
+ return ret;
+}
+
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ unsigned char *addtl_input, size_t addtllen)
+{
+ int ret = 0;
+ unsigned char w[DRBG_HASH_BLK];
+ struct drbg_conc data1, data2, data3;
+
+ DRBG_CLEAR_HASH_BLK(w);
+ DRBG_CLEAR_CONC(data1);
+ DRBG_CLEAR_CONC(data2);
+ DRBG_CLEAR_CONC(data3);
+
+ /* 10.1.1.4 step 2 */
+ if(0 == addtllen)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ data1.next = &data2;
+ data2.next = &data3;
+ data1.in = (unsigned char *) "\2";
+ data1.len = 1;
+ data2.in = drbg->V;
+ data2.len = DRBG_STATELEN(drbg);
+ data3.in = addtl_input;
+ data3.len = addtllen;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg->core->cipher_fn(drbg, NULL, w, &data1);
+ if(ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, DRBG_STATELEN(drbg), w, DRBG_BLOCKLEN(drbg));
+
+out:
+ DRBG_CLEAR_HASH_BLK(w);
+ return ret;
+}
+
+static int drbg_hash_preprocess_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst,
+ short *length)
+{
+ memset(drbg->scratchpad, 0,
+ (DRBG_STATELEN(drbg) + DRBG_BLOCKLEN(drbg)));
+ memcpy(drbg->scratchpad, drbg->V, DRBG_STATELEN(drbg));
+
+ *src = (unsigned char *)drbg->scratchpad;
+ *dst = (unsigned char *)drbg->scratchpad + DRBG_STATELEN(drbg);
+ *length = DRBG_STATELEN(drbg);
+
+ return 0;
+}
+
+static void drbg_hash_postprocess_extract(struct drbg_state *drbg,
+ unsigned char *src,
+ unsigned char *dst, int notlast)
+{
+ /* 10.1.1.4 hashgen step 4.3 */
+ if(notlast)
+ drbg_add_buf(src, DRBG_STATELEN(drbg),
+ (unsigned char *) "\1", 1);
+}
+
+static void drbg_hash_cleanup_extract(struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst)
+{
+ memset(drbg->scratchpad, 0,
+ (DRBG_STATELEN(drbg) + DRBG_BLOCKLEN(drbg)));
+}
+
+static int drbg_hash_newstate_postgen(struct drbg_state *drbg,
+ unsigned char *addtl_input,
+ size_t addtllen)
+{
+ int ret = 0;
+ unsigned char req[8], H[DRBG_HASH_BLK];
+ struct drbg_conc data1, data2;
+
+ DRBG_CLEAR_HASH_BLK(H);
+ DRBG_CLEAR_CONC(data1);
+ DRBG_CLEAR_CONC(data2);
+
+ /* 10.1.1.4 step 4 */
+ data1.next = &data2;
+ data1.in = (unsigned char *) "\3";
+ data1.len = 1;
+ data2.in = drbg->V;
+ data2.len = DRBG_STATELEN(drbg);
+ ret = drbg->core->cipher_fn(drbg, NULL, H, &data1);
+ if(ret)
+ goto out;
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, DRBG_STATELEN(drbg),
+ H, DRBG_BLOCKLEN(drbg));
+ drbg_add_buf(drbg->V, DRBG_STATELEN(drbg),
+ drbg->C, DRBG_STATELEN(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, DRBG_STATELEN(drbg), req, 8);
+
+out:
+ DRBG_CLEAR_HASH_BLK(H);
+ return ret;
+}
+
+static struct drbg_state_ops drbg_hash_ops = {
+ .process_addtl = drbg_hash_process_addtl,
+ .preprocess_extract = drbg_hash_preprocess_extract,
+ .postprocess_extract = drbg_hash_postprocess_extract,
+ .cleanup_extract = drbg_hash_cleanup_extract,
+ .newstate_postgen = drbg_hash_newstate_postgen,
+ .update_state = drbg_hash_update_state,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Set up the pointers to the right DRBG type implementations
+ *
+ * @drbg DRBG handle
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static inline int drbg_add_callbacks(struct drbg_state *drbg)
+{
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ if(drbg->flags & DRBG_HMAC_MASK) {
+ drbg->d_ops = &drbg_hmac_ops;
+ return 0;
+ }
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ if(drbg->flags & DRBG_HASH_MASK) {
+ drbg->d_ops = &drbg_hash_ops;
+ return 0;
+ }
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ if(drbg->flags & DRBG_CTR_MASK) {
+ drbg->d_ops = &drbg_ctr_ops;
+ return 0;
+ }
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ return -EOPNOTSUPP;
+}
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @perslen: size of personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, unsigned char *pers,
+ size_t perslen, int reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_conc data1, data2;
+
+ DRBG_CLEAR_CONC(data1);
+ DRBG_CLEAR_CONC(data2);
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if(perslen > (drbg_max_addtl(drbg)))
+ return -EINVAL;
+
+ /* section 8.6.1 together with section 8.6.3 and 8.6.7 -- consider DRBG
+ * seeded only when sufficient seed is provided */
+ /* Sufficient seed is provided: when we have no derivation function,
+ * a nonce is not necessary, if we have a derivation function, a nonce
+ * is necessary. A nonce must be at least 1/2 of the security strength
+ * of the DRBG in size. Thus, entropy * nonce is 3/2 of the strength.
+ *
+ * The consideration of a nonce is only applicable during initial
+ * seeding.
+ */
+
+ /* chapter 9: No seed is provided, the DRBG shall get its own seed */
+ if(drbg->test_data) {
+ data1.in = drbg->test_data->testentropy;
+ data1.len = drbg->test_data->testentropylen;
+ } else {
+ entropylen = (drbg_sec_strength(drbg->flags) / 8);
+ if(0 == reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if(!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ data1.in = entropy;
+ data1.len = entropylen;
+ }
+
+ /* 10.1.1.2 step 1 and 10.1.1.3 step 1 (concatenation of entropy /
+ * addtl input) */
+ if(0 < perslen) {
+ data1.next = &data2;
+ data2.in = pers;
+ data2.len = perslen;
+ }
+
+ ret = drbg->d_ops->update_state(drbg, &data1, reseed);
+ if(ret)
+ goto out;
+
+ drbg->flags &= ~(DRBG_UNSEEDED);
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Check for reseeding of the DRBG and invoke reseeding if necessary.
+ * This includes the enforcement of the prediction resistance as well
+ * as the reseeding constraint set by the SP800-90A requirement.
+ *
+ * @drbg: DRBG state struct
+ * @addtl_input: addition input for reseeding
+ * @addtllen: length of additional input
+ *
+ * return:
+ * 0 on success -- implies a successful reseeding of the DRBG handle
+ * error value otherwise
+ */
+static int drbg_check_reseed(struct drbg_state *drbg,
+ unsigned char **addtl_input, size_t *addtllen)
+{
+ int ret = 0;
+
+ if((drbg_max_requests(drbg)) < drbg->reseed_ctr)
+ drbg->flags |= DRBG_UNSEEDED;
+
+ /* section 9.3.1 step 6 and 7 */
+ if(!(drbg->flags & DRBG_PREDICTION_RESIST) &&
+ !(drbg->flags & DRBG_UNSEEDED))
+ return 0;
+ ret = drbg_seed(drbg, *addtl_input, *addtllen, 1);
+
+ /* This is NOT documented, but needed! */
+ *addtl_input = NULL;
+ *addtllen = 0;
+
+ return ret;
+}
+
+/*
+ * Sanity check of state during drbg_generate() -- we check for:
+ * reseeding requirement
+ * maximum number of requested bits
+ *
+ * @drbg: DRBG state struct
+ * @strength: requested minimum strength of DRBG
+ * @buflen: size of requested random number
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static inline int drbg_generate_sanity(struct drbg_state *drbg, size_t buflen,
+ unsigned char *pers, size_t perslen)
+{
+ if(NULL == drbg)
+ return -EINVAL;
+ if(NULL == drbg->core)
+ return -EINVAL;
+ if(NULL == drbg->V)
+ return -EINVAL;
+ if(NULL == drbg->C)
+ return -EINVAL;
+ if(NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if(perslen > (drbg_max_addtl(drbg)))
+ return -EINVAL;
+ if(NULL == pers && 0 < perslen)
+ return -EINVAL;
+
+ /* 9.3.1 step 2 -- max_bits is in bits, but buflen is in bytes */
+ if(buflen > (drbg_max_request_bytes(drbg)))
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if(drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if(0 == fips_enabled)
+ return true;
+ if(!drbg->prev) {
+ drbg->prev = kzalloc(DRBG_BLOCKLEN(drbg), GFP_KERNEL);
+ if(!drbg->prev)
+ return -ENOMEM;
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
+ memcpy(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
+ /* invert the memcmp result, because the test shall pass when the
+ * two compared values do not match */
+ if(ret)
+ return true;
+ else
+ return false;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Heavy lifting function of generating random numbers by generating
+ * blockwise output via cipher and ensuring that the last block is truncated
+ * to the proper length.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data
+ * @buflen length of output buffer
+ *
+ * return: generated bytes
+ */
+static unsigned int drbg_extract_bytes(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ int ret = 0;
+ /* 10.1.1.4 step 1 */
+ unsigned int len = 0;
+ unsigned char *src = NULL;
+ unsigned char *dst = NULL;
+ short length = 0;
+ struct drbg_conc data;
+
+ DRBG_CLEAR_CONC(data);
+
+ /* set up the source buffers and destination buffers as needed for
+ * the DRBG type -- the source buffer is fed into the cipher operation
+ * and the destination buffer will hold the result of the cipher
+ * operation */
+ ret = drbg->d_ops->preprocess_extract(drbg, &src, &dst, &length);
+ if(ret)
+ return 0;
+ data.in = src;
+ data.len = length;
+
+ /* potential integer overflow is covered by drbg_generate_sanity which
+ * ensures that buflen cannot overflow a signed int */
+ while(len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1, 10.1.2.5 step 4.1,
+ * 10.2.1.5.2 step 4.2 */
+ ret = drbg->core->cipher_fn(drbg, drbg->C, dst, &data);
+ if(ret)
+ goto out;
+ outlen = (DRBG_BLOCKLEN(drbg) < (buflen - len)) ?
+ DRBG_BLOCKLEN(drbg) : (buflen - len);
+ if(!drbg_fips_continuous_test(drbg, dst)) {
+ /* Continuous test failed or is just primed -- generate
+ * next round without copying the generated value out
+ * to the caller -- potential for a deadlock, but
+ * this error cannot mathematically occur. If it
+ * occurs, the integrity of the entire kernel is
+ * lost. */
+ drbg->d_ops->postprocess_extract(drbg, src, dst,
+ (len < buflen));
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2, 10.1.2.5 step 4.2,
+ * 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* Advance the buffers, if needed by the DRBG type */
+ drbg->d_ops->postprocess_extract(drbg, src, dst,
+ (len < buflen));
+ }
+
+out:
+ /* Allow DRBG type implementations to cleanup any temporary buffers
+ * set up when defining source and destination buffers
+ */
+ drbg->d_ops->cleanup_extract(drbg, &src, &dst);
+ return len;
+}
+
+/*
+ * Process request to generate random numbers. This function ensures
+ * that the additional information / personalization string is processed
+ * before bytes are generated. Also, this function ensures that the DRBG
+ * state is updated after random number generation.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data
+ * @buflen length of output buffer
+ * @addtl_input Additional input / personalization string buffer
+ * @addtllen Length of additional input buffer
+ *
+ * return: generated bytes
+ */
+static unsigned int drbg_generate_bytes(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ unsigned char *addtl_input,
+ size_t addtllen)
+{
+ unsigned int len = 0;
+
+ /* 10.1.1.4 step 2, 10.1.2.5 step 2, 10.2.1.5.2 step 2 */
+ if(drbg->d_ops->process_addtl(drbg, addtl_input, addtllen))
+ return 0;
+ /* 10.1.1.4 step 3, 10.1.2.5 step 3, 10.2.1.5.2 step 3 */
+ len = drbg_extract_bytes(drbg, buf, buflen);
+
+ /* 10.1.1.4 step 4 and following, 10.1.2.5 step 6, 10.2.1.5.2 step 6 */
+ if(drbg->d_ops->newstate_postgen(drbg, addtl_input, addtllen))
+ return 0;
+ return len;
+}
+
+/*
+ * Check for programming errors: ensure that stack variable size is
+ * sufficient for ciphers.
+ *
+ * @flags flags specifying the core cipher type
+ * @core selected core
+ *
+ * return:
+ * true if sanity check passed
+ * false if sanity check failed
+ */
+static inline bool drbg_check_progamming_sanity(drbg_flag_t flags,
+ const struct drbg_core *core)
+{
+ size_t size = 0;
+ if(flags & DRBG_CTR_MASK)
+ size = DRBG_CTR_BLK;
+ else if (flags & DRBG_HASH_MASK)
+ size = DRBG_HASH_BLK;
+ else if (flags & DRBG_HMAC_MASK)
+ size = DRBG_HMAC_BLK;
+ return (size >= core->statelen);
+}
+
+/*
+ * Find the right cipher callback data structure that matches the
+ * the requested cipher type. The code returns the first match in case caller
+ * made the error to request multiple ciphers
+ *
+ * @flags Flags handed in by caller during instantiation request
+ *
+ * return:
+ * pointer to core on success
+ * NULL on error
+ */
+static const inline struct drbg_core *drbg_find_core(drbg_flag_t flags)
+{
+ drbg_flag_t req_cipher = (flags & DRBG_CIPHER_MASK);
+ int i = 0;
+
+ for(i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if(req_cipher & cores[i].flags) {
+ if(drbg_check_progamming_sanity(req_cipher, &cores[i]))
+ return &cores[i];
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @perslen Length of personalization string buffer, shall be 0 when buffer
+ * is NULL
+ * @flags Flags defining the requested DRBG type and cipher type. The flags
+ * are defined in drbg.h and may be XORed. Beware, if you XOR multiple
+ * cipher types together, the code picks the core on a first come first
+ * serve basis as it iterates through the available cipher cores and
+ * uses the one with the first match. The minimum required flags are:
+ * cipher type flag
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+
+static int drbg_instantiate(struct drbg_state *drbg,
+ unsigned char *pers, size_t perslen,
+ drbg_flag_t flags)
+{
+ int ret = -ENOMEM;
+ const struct drbg_core *core = NULL;
+
+ core = drbg_find_core(flags);
+ if(NULL == core)
+ return -EINVAL;
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ drbg->V = kzalloc(core->statelen, GFP_KERNEL);
+ if(!drbg->V)
+ goto err;
+ drbg->C = kzalloc(core->statelen, GFP_KERNEL);
+ if(!drbg->C)
+ goto err;
+
+ /* the Hash DRBG needs full buffer, CTR needs only blocklen_bytes and
+ * HMAC does not need buffer at all */
+ drbg->scratchpad = kzalloc(core->statelen + core->blocklen_bytes,
+ GFP_KERNEL);
+ if(!drbg->scratchpad)
+ goto err;
+
+ spin_lock_init(&drbg->drbg_lock);
+
+ drbg->flags = flags;
+ drbg->flags |= DRBG_UNSEEDED;
+ drbg->core = core;
+
+ if(core->init_lib)
+ if(core->init_lib(drbg))
+ return -EFAULT;
+
+ ret = drbg_add_callbacks(drbg);
+ if(ret)
+ goto err;
+
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, perslen, 0);
+ if(ret)
+ goto err;
+
+ return 0;
+
+err:
+ if(drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if(drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if(drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ * @free_state free the DRBG state handle in addition to zeroization
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ /* ensure that other threads have their chance to complete their work */
+ spin_lock_bh(&drbg->drbg_lock);
+ if(drbg->core->fini_lib)
+ drbg->core->fini_lib(drbg);
+ if(drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if(drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if(drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+#ifdef CONFIG_CRYPTO_FIPS
+ if(drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+#endif
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl_input Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @addtllen Length of additional input buffer, shall be 0 when buffer is NULL
+ *
+ * return: generated number of bytes
+ */
+static unsigned int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ unsigned char *addtl_input, size_t addtllen)
+{
+ unsigned int len = 0;
+
+ if(0 == buflen)
+ return 0;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ if(drbg_generate_sanity(drbg, buflen, addtl_input, addtllen))
+ goto out;
+
+ if(drbg_check_reseed(drbg, &addtl_input, &addtllen))
+ goto out;
+
+ len = drbg_generate_bytes(drbg, buf, buflen, addtl_input, addtllen);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ drbg->reseed_ctr++;
+
+out:
+ spin_unlock_bh(&drbg->drbg_lock);
+ return len;
+}
+
+/*
+ * DRBG reseed function as required by SP800-90A
+ *
+ * @drbg DRBG state handle
+ * @addtl_input Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @addtllen Length of additional input buffer, shall be 0 when buffer is NULL
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+/* The kernel crypto API does not implement a reseeding function API call.
+ * This function should be enabled once a reseeding API call is implemented.
+ */
+#if 0
+static int drbg_reseed(struct drbg_state *drbg, unsigned char *addtl_input,
+ size_t addtllen)
+{
+ int ret = 0;
+ spin_lock_bh(&drbg->drbg_lock);
+ ret = drbg_seed(drbg, addtl_input, addtllen, 1);
+ spin_unlock_bh(&drbg->drbg_lock);
+ return ret;
+}
+#endif
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if(!test_data)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct shash_desc *shash;
+ int size;
+ struct crypto_shash *tfm;
+
+ /* allocate synchronous hash */
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ printk("drbg: could not allocate digest TFM handle\n");
+ return -EFAULT;
+ }
+
+ size = sizeof(struct shash_desc);
+ shash = kzalloc(size, GFP_KERNEL);
+ if (!shash) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+ shash->tfm = tfm;
+ shash->flags = 0x0;
+ drbg->priv_data = shash;
+
+ return ret;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
+ if(shash) {
+ crypto_free_shash(shash->tfm);
+ kzfree(shash);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in)
+{
+ struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
+ crypto_shash_init(shash);
+ for(; NULL != in; in = in->next)
+ crypto_shash_update(shash, in->in, in->len);
+ return crypto_shash_final(shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+static int drbg_kcapi_hmac(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in)
+{
+ int ret = 0;
+ struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
+ ret = crypto_shash_setkey(shash->tfm, key, DRBG_STATELEN(drbg));
+ if(ret)
+ return ret;
+ return drbg_kcapi_hash(drbg, key, outval, in);
+}
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct blkcipher_desc *desc;
+ struct crypto_blkcipher *blkcipher;
+
+ /* allocate synchronous cipher */
+ blkcipher = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if(IS_ERR(blkcipher)) {
+ printk("drbg: could not allocate cipher TFM handle\n");
+ return -EFAULT;
+ }
+
+ desc = kzalloc(sizeof(struct blkcipher_desc), GFP_KERNEL);
+ if (!desc) {
+ crypto_free_blkcipher(blkcipher);
+ return -ENOMEM;
+ }
+ desc->tfm = blkcipher;
+ desc->flags = 0;
+ drbg->priv_data = desc;
+
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct blkcipher_desc *desc =
+ (struct blkcipher_desc *)drbg->priv_data;
+ if(desc) {
+ crypto_free_blkcipher(desc->tfm);
+ kzfree(desc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc *desc =
+ (struct blkcipher_desc *)drbg->priv_data;
+
+ if(crypto_blkcipher_setkey(desc->tfm, key, (DRBG_KEYLEN(drbg))))
+ return -EFAULT;
+ /* in is only component */
+ sg_init_one(&sg_in, in->in, in->len);
+ sg_init_one(&sg_out, outval, DRBG_BLOCKLEN(drbg));
+ ret = crypto_blkcipher_encrypt(desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ *
+ * return: flags
+ */
+static drbg_flag_t drbg_convert_tfm_flags(const char *cra_name)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+ drbg_flag_t pr_flag = DRBG_PREDICTION_RESIST;
+
+ /* disassemble the names */
+ if(0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ pr_flag = 0;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else
+ return 0;
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+
+ for(i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if(0 == memcmp(cra_name + start, cores[i].cra_name, len))
+ /* add the prediction resistance flag, if drbg(pr(()))
+ * is selected */
+ return (cores[i].flags | pr_flag);
+ }
+ return 0;
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ drbg_flag_t flags = 0;
+
+ flags = drbg_convert_tfm_flags(crypto_tfm_alg_name(tfm));
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, 0, flags);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if(0 < dlen) {
+ return drbg_generate(drbg, rdata, dlen,
+ NULL, 0);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate(drbg, data->outbuf, data->outlen,
+ data->addtl_input, data->addtllen);
+ }
+}
+
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ drbg_flag_t flags = 0;
+
+ drbg_uninstantiate(drbg);
+ flags = drbg_convert_tfm_flags(crypto_tfm_alg_name(tfm_base));
+ if(0 < slen) {
+ return drbg_instantiate(drbg, seed, slen, flags);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl_input, data->addtllen,
+ flags);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static void __init drbg_fill_array(unsigned long i, unsigned long j, int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if(pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))", 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize= sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static void __init drbg_create_algs(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+
+ if(ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ printk("drbg: Not all available DRBGs registered (slots needed:"
+ "%lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for(j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+}
+
+static int __init drbg_init(void)
+{
+ drbg_create_algs();
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Determinist Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
+
--
1.8.5.3
The header file includes the definition of:
* DRBG data structures with
- struct drbg_state as main structure
- struct drbg_core referencing the backend ciphers
- struct drbg_state_ops callbach handlers for specific code
supporting the Hash, HMAC, CTR DRBG implementations
- struct drbg_conc defining a linked list for input data
- struct drbg_test_data holding the test "entropy" data for CAVS
testing and testmgr.c
- struct drbg_gen allowing test data, additional information
string and personalization string data to be funneled through
the kernel crypto API -- the DRBG requires additional
parameters when invoking the reset and random number
generation requests than intended by the kernel crypto API
* wrapper function to the kernel crypto API functions using struct
drbg_gen to pass through all data needed for DRBG
* wrapper functions to kernel crypto API functions usable for testing
code to inject test_data into the DRBG as needed by CAVS testing and
testmgr.c.
* DRBG flags required for the operation of the DRBG and for selecting
the particular DRBG type and backend cipher
* getter functions for data from struct drbg_core
Signed-off-by: Stephan Mueller <[email protected]>
create mode 100644 include/crypto/drbg.h
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
new file mode 100644
index 0000000..16515f9
--- /dev/null
+++ b/include/crypto/drbg.h
@@ -0,0 +1,340 @@
+/*
+ * DRBG based on NIST SP800-90A
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _DRBG_H
+#define _DRBG_H
+
+
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <crypto/hash.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/slab.h> /* needed for kzalloc */
+#include <crypto/internal/rng.h>
+#include <crypto/rng.h>
+#include <linux/fips.h>
+#include <linux/spinlock.h>
+
+/*
+ * Concatenation Helper
+ *
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+
+struct drbg_conc
+{
+ unsigned char *in;
+ size_t len;
+ struct drbg_conc *next;
+};
+
+#define DRBG_CLEAR_CONC(x) \
+ x.in = NULL; \
+ x.len = 0; \
+ x.next = NULL;
+
+struct drbg_state;
+typedef uint32_t drbg_flag_t;
+
+struct drbg_core
+{
+ drbg_flag_t flags; /* flags for the cipher */
+ __u8 statelen; /* maximum state length */
+ __u8 max_addtllen; /* maximum length of personalization string or
+ additional input string -- exponent for base
+ 2 */
+ __u8 max_bits; /* maximum bits per RNG request -- exponent for
+ base 2*/
+ __u8 max_req; /* maximum number of requests -- exponent for
+ base 2 */
+ __u8 blocklen_bytes; /* block size of output in bytes */
+ char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
+ char cra_driver_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto
+ * API */
+ char backend_cra_name[CRYPTO_MAX_ALG_NAME]; /* kernel crypto API
+ * backend cipher name */
+ int (*cipher_fn) (struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_conc *in);
+ int (*init_lib) (struct drbg_state *drbg);
+ int (*fini_lib) (struct drbg_state *drbg);
+
+};
+
+struct drbg_state_ops
+{
+ int (*process_addtl) (struct drbg_state *drbg,
+ unsigned char *addtl_input, size_t addtllen);
+ int (*preprocess_extract) (struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst, short *length);
+ void (*postprocess_extract) (struct drbg_state *drbg,
+ unsigned char *src,
+ unsigned char *dst, int notlast);
+ void (*cleanup_extract) (struct drbg_state *drbg,
+ unsigned char **src,
+ unsigned char **dst);
+ int (*newstate_postgen) (struct drbg_state *drbg,
+ unsigned char *addtl_input,
+ size_t addtllen);
+ int (*update_state) (struct drbg_state *drbg, struct drbg_conc *seed,
+ int reseed);
+};
+
+struct drbg_test_data
+{
+ unsigned char *testentropy; /* TEST PARAMETER: test entropy */
+ size_t testentropylen; /* TEST PARAMETER: length of test entropy */
+};
+
+/* use stack for variables instead of heap */
+#define DRBG_CTR_BLK 48
+#define DRBG_HASH_BLK 111
+#define DRBG_HMAC_BLK 64
+#define DRBG_CLEAR_CTR_BLK(x) memset(x, 0, DRBG_CTR_BLK);
+#define DRBG_CLEAR_HASH_BLK(x) memset(x, 0, DRBG_HASH_BLK);
+#define DRBG_CLEAR_HMAC_BLK(x) memset(x, 0, DRBG_HMAC_BLK);
+
+#define CLEAR_CRA_NAME(x) memset(x, 0, CRYPTO_MAX_ALG_NAME)
+
+struct drbg_state
+{
+ drbg_flag_t flags; /* Security strength */
+ spinlock_t drbg_lock; /* lock around DRBG */
+ unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *C; /* hash: static value 10.1.1.1 1b)
+ * hmac: key */
+ size_t reseed_ctr; /* Number of RNG requests since last reseed --
+ * 10.1.1.1 1c) */
+ unsigned char *scratchpad; /* some memory the DRBG can use for its
+ * operation -- allocated during init */
+ void *priv_data; /* Data needed for specific cipher
+ * implementation */
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned char *prev; /* previous output value of DRBG_BLOCKLEN for
+ * FIPS 140-2 continuous test */
+#endif
+ struct drbg_state_ops *d_ops;
+ const struct drbg_core *core;
+ struct drbg_test_data *test_data;
+};
+
+/* kernel crypto API input data structure for DRBG generate in case dlen
+ * is set to 0 */
+struct drbg_gen
+{
+ unsigned char *outbuf; /* output buffer for random numbers */
+ unsigned int outlen; /* size of output buffer */
+ unsigned char *addtl_input; /* input buffer for
+ * additional information string */
+ unsigned int addtllen; /* length of addtl_input */
+ struct drbg_test_data *test_data; /* test data */
+};
+
+/*
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ unsigned char *addtl_input, size_t addtllen)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl_input = addtl_input;
+ genbuf.addtllen = addtllen;
+ genbuf.test_data = NULL;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data and
+ * allow furnishing of test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ unsigned char *addtl_input, size_t addtllen,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl_input = addtl_input;
+ genbuf.addtllen = addtllen;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_reset() to allow the caller to provide test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_reset
+ * @pers personalization string input buffer
+ * @perslen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_reset
+ */
+static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
+ unsigned char *pers, unsigned int perslen,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = NULL;
+ genbuf.outlen = 0;
+ genbuf.addtl_input = pers;
+ genbuf.addtllen = perslen;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_reset(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+
+#define DRBG_STATELEN(a) ((a)->core->statelen)
+#define DRBG_BLOCKLEN(a) ((a)->core->blocklen_bytes)
+/* only needed for CTR mode -- implicit key len with seedlen - blocklen
+ * according to table 3 */
+#define DRBG_KEYLEN(drbg) (DRBG_STATELEN(drbg) - DRBG_BLOCKLEN(drbg))
+
+/*
+ * DRBG flags bitmasks
+ *
+ * 31 (B) 27 19 (A) 0
+ * +-+-+-+-+------+---+---+---------------+
+ * |~|~|u|p|~~~~~~| 3 | 2 | 1 |
+ * +-+-+-+-+------+- -+---+---------------+
+ * ctl flags| |drbg use selection flags
+ *
+ */
+
+/* internal state control flags (B) */
+#define DRBG_UNSEEDED ((drbg_flag_t)1<<27)
+#define DRBG_PREDICTION_RESIST ((drbg_flag_t)1<<28)
+
+/* CTR type modifiers (A.1)*/
+#define DRBG_CTRAES128 ((drbg_flag_t)1<<0)
+#define DRBG_CTRAES192 ((drbg_flag_t)1<<1)
+#define DRBG_CTRAES256 ((drbg_flag_t)1<<2)
+#define DRBG_CTRSERPENT128 ((drbg_flag_t)1<<3)
+#define DRBG_CTRSERPENT192 ((drbg_flag_t)1<<4)
+#define DRBG_CTRSERPENT256 ((drbg_flag_t)1<<5)
+#define DRBG_CTRTWOFISH128 ((drbg_flag_t)1<<6)
+#define DRBG_CTRTWOFISH192 ((drbg_flag_t)1<<7)
+#define DRBG_CTRTWOFISH256 ((drbg_flag_t)1<<8)
+#define DRBG_CTR_MASK (DRBG_CTRAES128 | DRBG_CTRAES192 | DRBG_CTRAES256| \
+ DRBG_CTRSERPENT128 | DRBG_CTRSERPENT192 | \
+ DRBG_CTRSERPENT256 | DRBG_CTRTWOFISH128 | \
+ DRBG_CTRTWOFISH192 | DRBG_CTRTWOFISH256)
+
+/* HASH type modifiers (A.2)*/
+#define DRBG_HASHSHA1 ((drbg_flag_t)1<<9)
+#define DRBG_HASHSHA224 ((drbg_flag_t)1<<10)
+#define DRBG_HASHSHA256 ((drbg_flag_t)1<<11)
+#define DRBG_HASHSHA384 ((drbg_flag_t)1<<12)
+#define DRBG_HASHSHA512 ((drbg_flag_t)1<<13)
+#define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 | \
+ DRBG_HASHSHA256 | DRBG_HASHSHA384 | \
+ DRBG_HASHSHA512)
+
+/* HMAC type modifiers (A.2)*/
+#define DRBG_HMACSHA1 ((drbg_flag_t)1<<14)
+#define DRBG_HMACSHA224 ((drbg_flag_t)1<<15)
+#define DRBG_HMACSHA256 ((drbg_flag_t)1<<16)
+#define DRBG_HMACSHA384 ((drbg_flag_t)1<<17)
+#define DRBG_HMACSHA512 ((drbg_flag_t)1<<18)
+#define DRBG_HMAC_MASK (DRBG_HMACSHA1 | DRBG_HMACSHA224 | \
+ DRBG_HMACSHA256 | DRBG_HMACSHA384 | \
+ DRBG_HMACSHA512)
+
+#define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK | DRBG_HMAC_MASK)
+
+/* helper functions */
+static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
+{
+ /* max_bits is in bits, but buflen is in bytes */
+ return (1 << (drbg->core->max_bits - 3));
+}
+
+static inline size_t drbg_max_addtl(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_addtllen));
+}
+
+static inline size_t drbg_max_requests(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_req));
+}
+
+#endif /* _DRBG_H */
--
1.8.5.3
The DRBG test code implements the CAVS test approach.
As discussed for the test vectors, all DRBG types are covered with
testing. However, not every backend cipher is covered with testing. To
prevent the testmgr from logging missing testing, the NULL test is
registered for all backend ciphers not covered with specific test cases.
All currently implemented DRBG types and backend ciphers are definined
in SP800-90A. Therefore, the fips_allowed flag is set for all.
Signed-off-by: Stephan Mueller <[email protected]>
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 7795550..e8cd57c 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/rng.h>
+#include <crypto/drbg.h>
#include "internal.h"
@@ -108,6 +109,11 @@ struct cprng_test_suite {
unsigned int count;
};
+struct drbg_test_suite {
+ struct drbg_testvec *vecs;
+ unsigned int count;
+};
+
struct alg_test_desc {
const char *alg;
int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -121,6 +127,7 @@ struct alg_test_desc {
struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
struct cprng_test_suite cprng;
+ struct drbg_test_suite drbg;
} suite;
};
@@ -1712,6 +1719,104 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
return err;
}
+
+static int drbg_cavs_test(struct drbg_testvec *test, int pr,
+ const char *driver, u32 type, u32 mask)
+{
+ int ret = -EAGAIN;
+ struct crypto_rng *drng;
+ struct drbg_state *drbg;
+ struct drbg_test_data test_data;
+ unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ drng = crypto_alloc_rng(driver, type, mask);
+ if(IS_ERR(drng)) {
+ printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for %s\n", driver);
+ return -ENOMEM;
+ }
+
+ drbg = crypto_tfm_ctx(crypto_rng_tfm(drng));
+ test_data.testentropy = test->entropy;
+ test_data.testentropylen = test->entropylen;
+ ret = crypto_drbg_reset_test(drng, test->pers, test->perslen,
+ &test_data);
+ if (ret) {
+ printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
+ goto outbuf;
+ }
+
+ if(pr) {
+ test_data.testentropy = test->entpra;
+ test_data.testentropylen = test->entprlen;
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen,
+ test->addtla, test->addtllen,
+ &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen,
+ test->addtla, test->addtllen);
+ }
+ if(ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data\n");
+ goto outbuf;
+ }
+
+ if(pr) {
+ test_data.testentropy = test->entprb;
+ test_data.testentropylen = test->entprlen;
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen,
+ test->addtlb, test->addtllen,
+ &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen,
+ test->addtlb, test->addtllen);
+ }
+ if(ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data\n");
+ goto outbuf;
+ }
+
+ ret = memcmp(test->expected, buf, test->expectedlen);
+
+outbuf:
+ crypto_free_rng(drng);
+ kzfree(buf);
+ return ret;
+}
+
+
+static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ int err = 0;
+ int pr = 0;
+ int i = 0;
+ struct drbg_testvec *template = desc->suite.drbg.vecs;
+ unsigned int tcount = desc->suite.drbg.count;
+
+ if((0 == memcmp(driver, "drbg(pr(", 8)) ||
+ (0 == memcmp(driver, "drbg_pr_", 8)))
+ pr = 1;
+
+ for (i = 0; i < tcount; i++)
+ {
+ err = drbg_cavs_test(&template[i], pr, driver, type, mask);
+ if (err) {
+ printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
+ i, driver);
+ err = -EINVAL;
+ break;
+ }
+ }
+ return err;
+
+}
+
static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
{
@@ -2273,6 +2378,170 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "digest_null",
.test = alg_test_null,
}, {
+ .alg = "drbg(nopr(ctr(aes128)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg(nopr(ctr(aes192)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes192_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes192_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg(nopr(ctr(aes256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha1)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(nopr(hmac(sha256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha384)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha512)))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha1))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(nopr(sha256))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg= {
+ .vecs = drbg_nopr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha384))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha512))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(ctr(aes128)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(aes128)) test */
+ .alg = "drbg(pr(ctr(aes192)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(aes128)) test */
+ .alg = "drbg(pr(ctr(aes256)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha1)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(hmac(sha256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha384)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha512)))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha1))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(sha256))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha384))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha512))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
.alg = "ecb(__aes-aesni)",
.test = alg_test_null,
.fips_allowed = 1,
--
1.8.5.3
All types of the DRBG (CTR, HMAC, Hash) are covered with test vectors.
In addition, all permutations of use cases of the DRBG are covered:
* with and without predition resistance
* with and without additional information string
* with and without personalization string
As the DRBG implementation is agnositc of the specific backend cipher,
only test vectors for one specific backend cipher is used. For example:
the Hash DRBG uses the same code paths irrespectively of using SHA-256
or SHA-512. Thus, the test vectors for SHA-256 cover the testing of all
DRBG code paths of SHA-512.
Signed-off-by: Stephan Mueller <[email protected]>
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 7d44aa3..2ee3bba 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -92,6 +92,29 @@ struct cprng_testvec {
unsigned short loops;
};
+struct drbg_testvec {
+ unsigned char *entropy; /* entropy string for initialization -- this
+ * string is a concatenation of the entropy
+ * and nonce variable from CAVS */
+ size_t entropylen; /* length of entropy and nonce variable */
+ unsigned char *entpra; /* for prediction resistance: entropy for
+ * first reseeding */
+ unsigned char *entprb; /* for prediction resistance: entropy for
+ * second reseeding */
+ size_t entprlen; /* length of prediction resistance entropy */
+ unsigned char *addtla; /* additional input string for first random
+ * value */
+ unsigned char *addtlb; /* additional input string for second random
+ * value */
+ size_t addtllen; /* length of additional input string */
+ unsigned char *pers; /* personalization string */
+ size_t perslen; /* personalization string length */
+ unsigned char *expected; /* expected random value -- for CAVS test,
+ this value does not apply and the memcmp
+ in drbg_cavs_test does not apply either*/
+ size_t expectedlen; /* length of expected random value */
+};
+
static char zeroed_string[48];
/*
@@ -19162,6 +19185,860 @@ static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
},
};
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG with prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+struct drbg_testvec drbg_pr_sha256_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86"
+ "\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf"
+ "\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6"
+ "\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62"
+ "\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f"
+ "\x67\xb0\x67\x7a\x5e\x9e\x0c\x62",
+ .entprb = (unsigned char *)
+ "\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf"
+ "\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0"
+ "\x8c\xee\xeb\x9c\xf5\x31\x98\x31",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7"
+ "\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49"
+ "\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d"
+ "\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe"
+ "\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1"
+ "\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5"
+ "\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf"
+ "\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6"
+ "\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5"
+ "\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce"
+ "\x30\x81\xa6\x8f\x27\x14\xf8\x1c",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
+ "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
+ "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
+ "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
+ "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
+ "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
+ .entprb = (unsigned char *)
+ "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
+ "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
+ "\x76\xaa\x55\x04\x8b\x0a\x72\x95",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
+ "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
+ "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
+ "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
+ "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
+ "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
+ "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
+ "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
+ "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
+ "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
+ "\x50\x47\xa3\x63\x81\x16\xaf\x19",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
+ "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
+ "\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
+ .addtlb = (unsigned char *)
+ "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
+ "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
+ "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85"
+ "\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72"
+ "\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8"
+ "\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9"
+ "\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60"
+ "\xba\x0a\xde\x57\x5b\x4b\x9f\x29",
+ .entprb = (unsigned char *)
+ "\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd"
+ "\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4"
+ "\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25"
+ "\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde"
+ "\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5"
+ "\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9"
+ "\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c"
+ "\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e"
+ "\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c"
+ "\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae"
+ "\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c"
+ "\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe"
+ "\x90\x35\x0d\x4c\x4d\x85\xe7\x13",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7"
+ "\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90"
+ "\xa4\x1b\xe1\xe2\x53\xcc\x61\x47",
+ .perslen = 32,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6"
+ "\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4"
+ "\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87"
+ "\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c"
+ "\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12"
+ "\x19\xaf\x97\x2d\x5f\xf9\xff\xfc",
+ .entprb = (unsigned char *)
+ "\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73"
+ "\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6"
+ "\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31"
+ "\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65"
+ "\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18"
+ "\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42"
+ "\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50"
+ "\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b"
+ "\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f"
+ "\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0"
+ "\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda"
+ "\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44"
+ "\x63\x4a\x68\x72\xe9\xf5\x55\xfe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c"
+ "\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff"
+ "\x4a\x85\xca\x80\xfe\x0d\x1c\xd0",
+ .addtlb = (unsigned char *)
+ "\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2"
+ "\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89"
+ "\x42\x58\x9e\xd6\xcc\xad\x7b\x1e",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1"
+ "\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52"
+ "\x82\x4c\xdc\x19\xb8\xf8\x92\x5c",
+ .perslen = 32,
+ },
+};
+
+struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a"
+ "\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96"
+ "\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46"
+ "\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92"
+ "\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46"
+ "\xe2\x9a\x29\x51\x81\x56\x9f\x54",
+ .entprb = (unsigned char *)
+ "\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc"
+ "\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65"
+ "\x8a\x2a\x77\xa8\x69\x90\x89\xf4",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2"
+ "\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1"
+ "\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4"
+ "\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf"
+ "\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc"
+ "\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8"
+ "\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b"
+ "\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e"
+ "\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22"
+ "\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc"
+ "\xb1\xcd\x09\xd6\x92\xd0\x28\x3f",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f"
+ "\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f"
+ "\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05"
+ "\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4"
+ "\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26"
+ "\x46\xd9\x26\xa2\x19\xd4\x94\x43",
+ .entprb = (unsigned char *)
+ "\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79"
+ "\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98"
+ "\x51\x78\x72\xb2\x79\xfd\x2c\xff",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7"
+ "\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda"
+ "\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa"
+ "\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40"
+ "\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda"
+ "\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37"
+ "\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70"
+ "\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b"
+ "\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5"
+ "\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd"
+ "\xcd\x66\xb5\x01\x69\x66\xa0\x3c",
+ .expectedlen = 128,
+ .addtla =(unsigned char *)
+ "\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3"
+ "\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56"
+ "\x6d\x99\x3b\xc6\x58\xda\x03\xf6",
+ .addtlb = (unsigned char *)
+ "\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c"
+ "\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44"
+ "\xc6\x03\xa2\xfb\x13\x20\x19\xb7",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
+ "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
+ "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
+ "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
+ "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
+ "\x20\x28\xad\xf2\x60\xd7\xcd\x45",
+ .entprb = (unsigned char *)
+ "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
+ "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
+ "\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
+ "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
+ "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
+ "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
+ "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
+ "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
+ "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
+ "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
+ "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
+ "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
+ "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
+ "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
+ "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
+ .perslen = 32,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd"
+ "\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01"
+ "\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15"
+ "\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a"
+ "\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96"
+ "\xbb\x81\x6a\xcc\xb5\xae\x55\xb6",
+ .entprb = (unsigned char *)
+ "\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2"
+ "\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e"
+ "\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14"
+ "\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6"
+ "\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7"
+ "\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77"
+ "\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5"
+ "\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6"
+ "\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1"
+ "\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40"
+ "\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8"
+ "\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72"
+ "\xda\x3f\xad\x2b\xba\x00\x6b\xd1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03"
+ "\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6"
+ "\x86\x88\x55\x28\xc1\x69\xdd\x76",
+ .addtlb = (unsigned char *)
+ "\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7"
+ "\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa"
+ "\x00\x99\x2a\xdd\x0a\x00\x50\x82",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8"
+ "\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda"
+ "\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
+ .perslen = 32,
+ },
+};
+
+struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42"
+ "\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15"
+ "\xb4\xec\x80\xb1",
+ .entprb = (unsigned char *)
+ "\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9"
+ "\x28\x07\xeb\xc2",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe"
+ "\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc"
+ "\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18"
+ "\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce"
+ "\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b"
+ "\x8a\xf1\x23\xa8",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77"
+ "\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73"
+ "\x67\xd1\x08\xf8",
+ .entprb = (unsigned char *)
+ "\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc"
+ "\xd4\xba\x04\x58",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d"
+ "\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc"
+ "\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7"
+ "\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc"
+ "\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c"
+ "\xc1\x02\x41\x82",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8"
+ "\xeb\xb3\x01\x76",
+ .addtlb = (unsigned char *)
+ "\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25"
+ "\xd0\x7f\xcc\x43",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b"
+ "\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66"
+ "\xc3\x0f\xe3\xb0",
+ .entprb = (unsigned char *)
+ "\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8"
+ "\xd6\x9c\x9d\xe8",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b"
+ "\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10"
+ "\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69"
+ "\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc"
+ "\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f"
+ "\x72\x82\x0c\xcf",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed"
+ "\x21\x52\xb3\xad",
+ .perslen = 16,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
+ "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
+ "\xc4\x2c\xe8\x10",
+ .entprb = (unsigned char *)
+ "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
+ "\x08\xf7\xa5\x01",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
+ "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
+ "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
+ "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
+ "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
+ "\x23\xc5\x1f\x68",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
+ "\x23\x6d\xad\x1d",
+ .addtlb = (unsigned char *)
+ "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
+ "\xbc\x59\x31\x8c",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
+ "\x37\x3c\x5c\x0b",
+ .perslen = 16,
+ },
+};
+
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG without prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+struct drbg_testvec drbg_nopr_sha256_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3"
+ "\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19"
+ "\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31"
+ "\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64"
+ "\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5"
+ "\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3"
+ "\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11"
+ "\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81"
+ "\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63"
+ "\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7"
+ "\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c"
+ "\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91"
+ "\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d"
+ "\xd4\x31\xf4\xc9\xf7\x04\x27\xdf",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
+ "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
+ "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
+ "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
+ "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
+ "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
+ "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
+ "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
+ "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
+ "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
+ "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
+ "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
+ "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
+ "\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
+ "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
+ "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
+ .addtlb = (unsigned char *)
+ "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
+ "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
+ "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb"
+ "\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4"
+ "\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1"
+ "\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28"
+ "\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b"
+ "\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46"
+ "\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6"
+ "\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72"
+ "\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1"
+ "\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77"
+ "\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9"
+ "\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e"
+ "\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16"
+ "\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1"
+ "\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda"
+ "\x57\x6b\xce\xa4\x1c\x66\x3d\xbc",
+ .perslen = 32,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a"
+ "\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74"
+ "\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc"
+ "\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb"
+ "\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13"
+ "\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6"
+ "\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36"
+ "\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64"
+ "\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea"
+ "\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95"
+ "\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e"
+ "\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd"
+ "\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06"
+ "\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2"
+ "\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e"
+ "\x77\xc5\x3d\x9e\x03\xe3\xa5\x78",
+ .addtlb = (unsigned char *)
+ "\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a"
+ "\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b"
+ "\x74\x7f\xa6\xf6\x80\xcd\x9b\x21",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20"
+ "\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73"
+ "\xa9\x65\xb1\x10\xc1\xdc\x77\x7c",
+ .perslen = 32,
+ },
+};
+
+struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
+ "\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
+ "\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c"
+ "\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75"
+ "\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6"
+ "\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97"
+ "\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60"
+ "\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf"
+ "\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99"
+ "\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19"
+ "\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68"
+ "\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0"
+ "\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd"
+ "\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94"
+ "\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15"
+ "\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4"
+ "\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5"
+ "\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf"
+ "\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d"
+ "\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6"
+ "\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16"
+ "\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62"
+ "\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d"
+ "\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4"
+ "\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec"
+ "\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f"
+ "\x50\x9a\x8c\x85\x90\x87\x03\x9c",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d"
+ "\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf"
+ "\x2f\xf3\x00\x34\xd8\x26\x8e\x3b",
+ .addtlb = (unsigned char *)
+ "\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9"
+ "\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14"
+ "\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
+ "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
+ "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
+ "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
+ "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
+ "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
+ "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
+ "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
+ "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
+ "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
+ "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
+ "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
+ "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
+ "\x10\x37\x41\x03\x0c\xcc\x3a\x56",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
+ "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
+ "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
+ .perslen = 32,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78"
+ "\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11"
+ "\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb"
+ "\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0"
+ "\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37"
+ "\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae"
+ "\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0"
+ "\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad"
+ "\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82"
+ "\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7"
+ "\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4"
+ "\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49"
+ "\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30"
+ "\x35\x24\xcc\x9c\xc5\xea\x54\xa1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96"
+ "\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62"
+ "\xd3\x13\x3b\x83\xe4\x9c\x82\x0b",
+ .addtlb = (unsigned char *)
+ "\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2"
+ "\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25"
+ "\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8"
+ "\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15"
+ "\x36\x60\x3b\xca\x37\xc9\xee\x29",
+ .perslen = 32,
+ },
+};
+
+struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9"
+ "\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40"
+ "\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9"
+ "\xac\x9b\xbb\x00",
+ .entropylen = 40,
+ .expected = (unsigned char *)
+ "\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17"
+ "\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33"
+ "\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48"
+ "\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79"
+ "\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf"
+ "\x9a\x9d\xf1\x0d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f"
+ "\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec"
+ "\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0"
+ "\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6"
+ "\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3"
+ "\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf"
+ "\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16"
+ "\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f"
+ "\xb4\xf0\x7e\x1d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] =
+{
+ {
+ .entropy = (unsigned char *)
+ "\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8"
+ "\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1"
+ "\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a"
+ "\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3"
+ "\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e"
+ "\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8"
+ "\xcb\x2d\xd6\xb0",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74"
+ "\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34"
+ "\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21"
+ "\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e"
+ "\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1"
+ "\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc"
+ "\xc3\xdf\xb3\x81",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6"
+ "\x91\x4d\x81\x56",
+ .addtlb = (unsigned char *)
+ "\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb"
+ "\x4a\x55\xd1\xc6",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9"
+ "\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e"
+ "\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75"
+ "\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee"
+ "\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb"
+ "\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45"
+ "\x34\x30\x0c\x3d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a"
+ "\x0b\xc6\x97\x54",
+ .perslen = 16,
+ },
+ {
+ .entropy = (unsigned char *)
+ "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
+ "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
+ "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
+ "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
+ "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
+ "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
+ "\x2b\x49\x1e\x5c",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
+ "\x44\x85\xe7\xfe",
+ .addtlb = (unsigned char *)
+ "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
+ "\x82\x16\x62\x7f",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
+ "\x8e\xcf\xe0\x02",
+ .perslen = 16,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 4
#define CAST5_DEC_TEST_VECTORS 4
--
1.8.5.3
On Sun, Mar 09, 2014 at 12:46:00AM +0100, Stephan Mueller wrote:
> This is a clean-room implementation of the DRBG defined in SP800-90A.
> All three viable DRBGs defined in the standard are implemented:
>
> * HMAC
> * Hash
> * CTR
>
> Signed-off-by: Stephan Mueller <[email protected]>
>
> create mode 100644 crypto/drbg.c
>
> diff --git a/crypto/drbg.c b/crypto/drbg.c
> new file mode 100644
> index 0000000..5308cce
> --- /dev/null
> +++ b/crypto/drbg.c
> @@ -0,0 +1,1941 @@
> +/*
> + * DRBG: Deterministic Random Bits Generator
> + * Based on NIST Recommended DRBG from NIST SP800-90A with the following
> + * properties:
> + * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
> + * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
> + * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
> + * * with and without prediction resistance
> + *
> + * Copyright Stephan Mueller <[email protected]>, 2014
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, and the entire permission notice in its entirety,
> + * including the disclaimer of warranties.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote
> + * products derived from this software without specific prior
> + * written permission.
> + *
> + * ALTERNATIVELY, this product may be distributed under the terms of
> + * the GNU General Public License, in which case the provisions of the GPL are
> + * required INSTEAD OF the above restrictions. (This clause is
> + * necessary due to a potential bad interaction between the GPL and
> + * the restrictions contained in a BSD-style copyright.)
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * DRBG Usage
> + * ==========
> + * The SP 800-90A DRBG allows the user to specify a personalization string
> + * for initialization as well as an additional information string for each
> + * random number request. The following code fragments show how a caller
> + * uses the kernel crypto API to use the full functionality of the DRBG.
> + *
> + * Usage without any additional data
> + * ---------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + *
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * err = crypto_rng_get_bytes(drng, &data, DATALEN);
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with personalization string during initialization
> + * -------------------------------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + * char personalization = "some-string";
> + *
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * // The reset completely re-initializes the DRBG with the provided
> + * // personalization string
> + * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
> + * err = crypto_rng_get_bytes(drng, &data, DATALEN);
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with additional information string during random number request
> + * ---------------------------------------------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + * char addtl = "some-string";
> + *
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * // The following call is a wrapper to crypto_rng_get_bytes() and returns
> + * // the same error codes.
> + * err = crypto_drbg_get_bytes_addtl(drng,
> + * &data, DATALEN,
> + * &addtl, strlen(addtl));
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with personalization and additional information strings
> + * -------------------------------------------------------------
> + * Just mix both scenarios above.
> + */
> +
> +#include <crypto/drbg.h>
> +
> +#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
> + !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
> + !defined(CONFIG_CRYPTO_DRBG_CTR)
> +#warning "The DRBG code is useless without compiling at least one DRBG type"
> +#endif
> +
> +/***************************************************************
> + * Backend cipher definitions available to DRBG
> + ***************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +static int drbg_kcapi_hmac(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in);
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
> +static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in);
> +static int drbg_init_hash_kernel(struct drbg_state *drbg);
> +static int drbg_fini_hash_kernel(struct drbg_state *drbg);
> +#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in);
> +static int drbg_init_sym_kernel(struct drbg_state *drbg);
> +static int drbg_fini_sym_kernel(struct drbg_state *drbg);
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +
> +const struct drbg_core cores[] =
> +{
> + /* Hash DRBGs */
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> + {
> + .flags = DRBG_HASHSHA1,
> + .statelen = 55, /* 440 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 20,
> + .cipher_fn = drbg_kcapi_hash,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "sha1",
> + .cra_driver_name = "sha1",
> + .backend_cra_name = "sha1",
> + }, {
> + .flags = DRBG_HASHSHA256,
> + .statelen = 55, /* 440 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 32,
> + .cipher_fn = drbg_kcapi_hash,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "sha256",
> + .cra_driver_name = "sha256",
> + .backend_cra_name = "sha256",
> + }, {
> + .flags = DRBG_HASHSHA384,
> + .statelen = 111, /* 888 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 48,
> + .cipher_fn = drbg_kcapi_hash,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "sha384",
> + .cra_driver_name = "sha384",
> + .backend_cra_name = "sha384",
> + }, {
> + .flags = DRBG_HASHSHA512,
> + .statelen = 111, /* 888 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 64,
> + .cipher_fn = drbg_kcapi_hash,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "sha512",
> + .cra_driver_name = "sha512",
> + .backend_cra_name = "sha512",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> + {
> + /* HMAC DRBGs */
> + .flags = DRBG_HMACSHA1,
> + .statelen = 20, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 20,
> + .cipher_fn = drbg_kcapi_hmac,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "hmac(sha1)",
> + .cra_driver_name = "hmac_sha1",
> + .backend_cra_name = "hmac(sha1)",
> + }, {
> + .flags = DRBG_HMACSHA256,
> + .statelen = 32, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 32,
> + .cipher_fn = drbg_kcapi_hmac,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "hmac(sha256)",
> + .cra_driver_name = "hmac_sha256",
> + .backend_cra_name = "hmac(sha256)",
> + }, {
> + .flags = DRBG_HMACSHA384,
> + .statelen = 48, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 48,
> + .cipher_fn = drbg_kcapi_hmac,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "hmac(sha384)",
> + .cra_driver_name = "hmac_sha384",
> + .backend_cra_name = "hmac(sha384)",
> + }, {
> + .flags = DRBG_HMACSHA512,
> + .statelen = 64, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 64,
> + .cipher_fn = drbg_kcapi_hmac,
> + .init_lib = drbg_init_hash_kernel,
> + .fini_lib = drbg_fini_hash_kernel,
> + .cra_name = "hmac(sha512)",
> + .cra_driver_name = "hmac_sha512",
> + .backend_cra_name = "hmac(sha512)",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> + {
> + /* block ciphers */
> + .flags = DRBG_CTRAES128,
> + .statelen = 32, /* 256 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cipher_fn = drbg_kcapi_sym,
> + .init_lib = drbg_init_sym_kernel,
> + .fini_lib = drbg_fini_sym_kernel,
> + .cra_name = "ctr(aes128)",
> + .cra_driver_name = "ctr_aes128",
> + .backend_cra_name = "ecb(aes)",
> +
> + }, {
> + /* block ciphers */
> + .flags = DRBG_CTRAES192,
> + .statelen = 40, /* 320 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cipher_fn = drbg_kcapi_sym,
> + .init_lib = drbg_init_sym_kernel,
> + .fini_lib = drbg_fini_sym_kernel,
> + .cra_name = "ctr(aes192)",
> + .cra_driver_name = "ctr_aes192",
> + .backend_cra_name = "ecb(aes)",
> + }, {
> + /* block ciphers */
> + .flags = DRBG_CTRAES256,
> + .statelen = 48, /* 384 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cipher_fn = drbg_kcapi_sym,
> + .init_lib = drbg_init_sym_kernel,
> + .fini_lib = drbg_fini_sym_kernel,
> + .cra_name = "ctr(aes256)",
> + .cra_driver_name = "ctr_aes256",
> + .backend_cra_name = "ecb(aes)",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +};
> +
> +/******************************************************************
> + * Generic helper functions
> + ******************************************************************/
> +
> +/*
> + * Return strength of DRBG according to SP800-90A section 8.4
> + *
> + * flags: DRBG flags reference
> + *
> + * Return: normalized strength value or 0 on error
> + */
> +static unsigned short drbg_sec_strength(drbg_flag_t flags)
> +{
> + switch(flags & DRBG_CIPHER_MASK) {
> + case DRBG_CTRAES128:
> + case DRBG_CTRSERPENT128:
> + case DRBG_CTRTWOFISH128:
> + case DRBG_HASHSHA1:
> + case DRBG_HMACSHA1:
> + return 128;
> + case DRBG_CTRAES192:
> + case DRBG_CTRSERPENT192:
> + case DRBG_CTRTWOFISH192:
> + return 192;
> + case DRBG_CTRAES256:
> + case DRBG_CTRSERPENT256:
> + case DRBG_CTRTWOFISH256:
> + case DRBG_HASHSHA256:
> + case DRBG_HASHSHA384:
> + case DRBG_HASHSHA512:
> + case DRBG_HMACSHA256:
> + case DRBG_HMACSHA384:
> + case DRBG_HMACSHA512:
> + return 256;
> + default:
> + return 0;
> + }
> +}
> +
> +#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
> +static inline void drbg_int2byte(unsigned char *buf, uint64_t val, size_t buflen)
> +{
> + unsigned char *byte;
> + uint64_t i;
> +
> + byte = buf + (buflen - 1);
> + for (i = 0; i < buflen; i++)
> + *(byte--) = val >> (i * 8) & 0xff;
> +}
> +
> +static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
> + unsigned char *add, size_t addlen)
> +{
> + /* implied: dstlen > addlen */
> + unsigned char *dstptr, *addptr;
> + unsigned int remainder = 0;
> + size_t len = addlen;
> +
> + dstptr = dst + (dstlen-1);
> + addptr = add + (addlen-1);
> + while(len) {
> + remainder += *dstptr + *addptr;
> + *dstptr = remainder & 0xff;
> + remainder >>= 8;
> + len--; dstptr--; addptr--;
> + }
> + len = dstlen - addlen;
> + while(len && remainder > 0) {
> + remainder = *dstptr + 1;
> + *dstptr = remainder & 0xff;
> + remainder >>= 8;
> + len--; dstptr--;
> + }
> +}
> +#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
> +
> +/******************************************************************
> + * CTR DRBG callback functions
> + ******************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_ctr_bcc(struct drbg_state *drbg,
> + unsigned char *out, unsigned char *key,
> + struct drbg_conc *in)
> +{
> + int ret = -EFAULT;
> + struct drbg_conc *curr = in;
> + size_t inpos = curr->len;
> + unsigned char *pos = curr->in;
> + struct drbg_conc data;
> +
> + DRBG_CLEAR_CONC(data);
> + data.in = out;
> + data.len = DRBG_BLOCKLEN(drbg);
> +
> + /* 10.4.3 step 1 */
> + memset(out, 0, DRBG_BLOCKLEN(drbg));
> +
> + /* 10.4.3 step 2 / 4 */
> + while(inpos) {
> + short cnt = 0;
> + /* 10.4.3 step 4.1 */
> + for(cnt = 0; cnt < DRBG_BLOCKLEN(drbg); cnt++) {
> + out[cnt] ^= *pos;
> + pos++; inpos--;
> + /* the following branch implements the linked list
> + * iteration. If we are at the end of the current data
> + * set, we have to start using the next data set if
> + * available -- the inpos value always points to the
> + * current byte and will be zero if we have processed
> + * the last byte of the last linked list member */
> + if(0 == inpos) {
> + curr = curr->next;
> + if(NULL != curr) {
> + pos = curr->in;
> + inpos = curr->len;
> + } else {
> + inpos = 0;
> + break;
> + }
> + }
> + }
> + /* 10.4.3 step 4.2 */
> + ret = drbg->core->cipher_fn(drbg, key, out, &data);
> + if(ret)
> + return ret;
> + /* 10.4.3 step 2 */
> + }
> + return 0;
> +}
> +
> +static int drbg_ctr_df(struct drbg_state *drbg,
> + unsigned char *out, size_t bytes_to_return,
> + struct drbg_conc *input)
> +{
> + int ret = -EFAULT;
> + unsigned char L_N[8];
> + /* S3 is input */
> + struct drbg_conc S1, S2, S4;
> + unsigned char temp[DRBG_CTR_BLK], pad[DRBG_CTR_BLK], IV[DRBG_CTR_BLK];
> + size_t padlen = 1; /* already reserve space for 0x80 */
> + int templen = 0;
> + /* 10.4.2 step 7 */
> + unsigned int i = 0;
> + /* 10.4.2 step 8 - truncation happens in ->cipher_fn which uses only
> + * DRBG_BLOCKLEN bits of key */
> + 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;
> + struct drbg_conc cipherin;
> + size_t generated_len = 0;
> + size_t inputlen = 0;
> + struct drbg_conc *tempconc = input;
> +
> + DRBG_CLEAR_CTR_BLK(pad);
> + DRBG_CLEAR_CTR_BLK(temp);
> + DRBG_CLEAR_CTR_BLK(IV);
> + DRBG_CLEAR_CONC(S1);
> + DRBG_CLEAR_CONC(S2);
> + DRBG_CLEAR_CONC(S4);
> +
> + /* 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*/
> + for(; NULL != tempconc; tempconc = tempconc->next)
> + inputlen += tempconc->len;
> +
> + drbg_int2byte(&L_N[0], inputlen, 4);
> + /* 10.4.2 step 3 */
> + drbg_int2byte(&L_N[4], bytes_to_return, 4);
> +
> + /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
> + while(0 != ((8 + inputlen + padlen) % (DRBG_BLOCKLEN(drbg))))
> + padlen++;
> + pad[0] = 0x80;
> +
> + /* 10.4.2 step 4 -- first arrange the linked list and then fill it */
> + S1.next = &S2;
> + S2.next = input;
> + /* splice in input between S2 and S4 -- we place S4 at the end of the
> + * input data chain */
> + tempconc = input;
> + for(; NULL != tempconc; tempconc = tempconc->next)
> + if(NULL == tempconc->next)
> + break;
> + tempconc->next = &S4;
> +
> + S1.in = IV;
> + S1.len = DRBG_BLOCKLEN(drbg);
> + S2.in = L_N;
> + S2.len = 8;
> + S4.in = pad;
> + S4.len = padlen;
> +
> + /* 10.4.2 step 9 */
> + while(templen < (DRBG_KEYLEN(drbg) + (DRBG_BLOCKLEN(drbg)))) {
> + /* 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 */
> + drbg_int2byte(IV, i, 4);
> + /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
> + ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
> + if(ret)
> + goto out;
> + /* 10.4.2 step 9.3 */
> + i++;
> + templen += DRBG_BLOCKLEN(drbg);
> + }
> +
> + /* 10.4.2 step 11 */
> + /* implicit key len with seedlen - blocklen according to table 3 */
> + X = temp + (DRBG_KEYLEN(drbg));
> + cipherin.in = X; cipherin.len = DRBG_BLOCKLEN(drbg);
> +
> + /* 10.4.2 step 12: overwriting of outval */
> +
> + /* 10.4.2 step 13 */
> + 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 -- check for the implementation
> + * of the cipher function callback */
> + ret = drbg->core->cipher_fn(drbg, temp, X, &cipherin);
> + if(ret)
> + goto out;
> + blocklen = (DRBG_BLOCKLEN(drbg) <
> + (bytes_to_return - generated_len)) ?
> + DRBG_BLOCKLEN(drbg) :
> + (bytes_to_return - generated_len);
> + /* 10.4.2 step 13.2 and 14 */
> + memcpy(out + generated_len, X, blocklen);
> + generated_len += blocklen;
> + }
> +
> + ret = 0;
> +
> +out:
> + DRBG_CLEAR_CTR_BLK(IV);
> + DRBG_CLEAR_CTR_BLK(temp);
> + DRBG_CLEAR_CTR_BLK(pad);
> + return ret;
> +}
> +
> +static int drbg_ctr_update_state(struct drbg_state *drbg,
> + struct drbg_conc *prov_data,
> + int reseed)
> +{
> + int ret = -EFAULT;
> + /* 10.2.1.2 step 1 */
> + unsigned char temp[DRBG_CTR_BLK], df_data[DRBG_CTR_BLK];
> + unsigned char *temp_p, *df_data_p; /* not malloced */
> + int len = 0;
> + struct drbg_conc cipherin;
> +
> + DRBG_CLEAR_CTR_BLK(temp);
> + DRBG_CLEAR_CTR_BLK(df_data);
> + DRBG_CLEAR_CONC(cipherin);
> +
> + /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
> + if(0 < prov_data->len) {
> + ret = drbg_ctr_df(drbg, df_data, DRBG_STATELEN(drbg),
> + prov_data);
> + if(ret)
> + goto out;
> + }
> +
> + cipherin.in = drbg->V; cipherin.len = DRBG_BLOCKLEN(drbg);
> + /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
> + * all memory during initialization */
> + while(len < (DRBG_STATELEN(drbg))) {
> + /* 10.2.1.2 step 2.1 */
> + drbg_add_buf(drbg->V, DRBG_BLOCKLEN(drbg),
> + (unsigned char *) "\1", 1);
> + /* 10.2.1.2 step 2.2 */
> + /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
> + ret = drbg->core->cipher_fn(drbg, drbg->C, temp + len,
> + &cipherin);
> + if(ret)
> + goto out;
> + /* 10.2.1.2 step 2.3 and 3 */
> + len += DRBG_BLOCKLEN(drbg);
> + }
> +
> + /* 10.2.1.2 step 4 */
> + temp_p = temp;
> + df_data_p = df_data;
> + for(len = 0; len < DRBG_STATELEN(drbg); len++) {
> + *temp_p ^= *df_data_p;
> + df_data_p++; temp_p++;
> + }
> +
> + /* 10.2.1.2 step 5 */
> + memcpy(drbg->C, temp, DRBG_KEYLEN(drbg));
> + /* 10.2.1.2 step 6 */
> + memcpy(drbg->V, temp + DRBG_KEYLEN(drbg), DRBG_BLOCKLEN(drbg));
> + ret = 0;
> +
> +out:
> + DRBG_CLEAR_CTR_BLK(df_data);
> + DRBG_CLEAR_CTR_BLK(temp);
> + return ret;
> +}
> +
> +static int drbg_ctr_process_addtl(struct drbg_state *drbg,
> + unsigned char *addtl_input, size_t addtllen)
> +{
> + struct drbg_conc addtl;
> + DRBG_CLEAR_CONC(addtl);
> + if(0 == addtllen)
> + return 0;
> + /* 10.2.1.5.2 step 2 */
> + addtl.in = addtl_input;
> + addtl.len = addtllen;
> + return drbg_ctr_update_state(drbg, &addtl, 1);
> +}
> +
> +static int drbg_ctr_preprocess_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst,
> + short *length)
> +{
> + memset(drbg->scratchpad, 0, DRBG_BLOCKLEN(drbg));
> + *src = drbg->V;
> + *dst = (unsigned char *)drbg->scratchpad;
> + *length = DRBG_BLOCKLEN(drbg);
> +
> + drbg_add_buf(*src, DRBG_BLOCKLEN(drbg),
> + (unsigned char *) "\1", 1);
> +
> + return 0;
> +}
> +
> +static void drbg_ctr_postprocess_extract(struct drbg_state *drbg,
> + unsigned char *src,
> + unsigned char *dst, int notlast)
> +{
> + /* 10.2.1.5.2 step 4.1 */
> + if(notlast)
> + drbg_add_buf(src, DRBG_BLOCKLEN(drbg),
> + (unsigned char *) "\1", 1);
> +}
> +
> +static void drbg_ctr_cleanup_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst)
> +{
> + memset(drbg->scratchpad, 0, DRBG_BLOCKLEN(drbg));
> +}
> +
> +static int drbg_ctr_newstate_postgen(struct drbg_state *drbg,
> + unsigned char *addtl_input,
> + size_t addtllen)
> +{
> + struct drbg_conc addtl;
> + DRBG_CLEAR_CONC(addtl);
> + addtl.in = addtl_input;
> + addtl.len = addtllen;
> + /* 10.1.2.5 step 6 */
> + /*TODO the DF function is called again since according to step
> + * 2, the "additional_input" after step 2 is the output of the DF
> + * function -- when we save the DF output as a replacement
> + * for the addtl_input data, we do not need to call the DF again here*/
> + return drbg_ctr_update_state(drbg, &addtl, 1);
> +}
> +
> +static struct drbg_state_ops drbg_ctr_ops = {
> + .process_addtl = drbg_ctr_process_addtl,
> + .preprocess_extract = drbg_ctr_preprocess_extract,
> + .postprocess_extract = drbg_ctr_postprocess_extract,
> + .cleanup_extract = drbg_ctr_cleanup_extract,
> + .newstate_postgen = drbg_ctr_newstate_postgen,
> + .update_state = drbg_ctr_update_state,
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +
> +/******************************************************************
> + * HMAC DRBG callback functions
> + ******************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +static int drbg_hmac_update_state(struct drbg_state *drbg,
> + struct drbg_conc *seed,
> + int reseed)
> +{
> + int ret = -EFAULT;
> + int i = 0;
> + struct drbg_conc seed1, seed2, cipherin;
> +
> + DRBG_CLEAR_CONC(seed1);
> + DRBG_CLEAR_CONC(seed2);
> + DRBG_CLEAR_CONC(cipherin);
> +
> + if(!reseed) {
> + /* 10.1.2.3 step 2 already implicitly covered with
> + * the initial memset(0) of drbg->C */
> + memset(drbg->C, 0, DRBG_STATELEN(drbg));
> + memset(drbg->V, 1, DRBG_STATELEN(drbg));
> + }
> +
> + /* build linked list which implements the concatenation and fill
> + * first part*/
> + seed1.next = &seed2;
> + seed2.next = seed;
> + seed1.in = drbg->V;
> + seed1.len = DRBG_STATELEN(drbg);
> +
> + cipherin.in = drbg->V;
> + cipherin.len = DRBG_STATELEN(drbg);
> + /* we execute two rounds of V/K massaging */
> + for(i = 2; 0 < i; i--) {
> + /* first round uses 0x0, second 0x1 */
> + unsigned char prefix = '\0';
> + if(1 == i)
> + prefix = '\1';
> +
> + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
> + seed2.in = &prefix;
> + seed2.len = 1;
> + ret = drbg->core->cipher_fn(drbg, drbg->C, drbg->C, &seed1);
> + if(ret)
> + return ret;
> +
> + /* 10.1.2.2 step 2 and 5 -- HMAC for V */
> + ret = drbg->core->cipher_fn(drbg, drbg->C, drbg->V, &cipherin);
> + if(ret)
> + return ret;
> +
> + /* 10.1.2.2 step 3 */
> + if(0 == seed->len)
> + return ret;
> + }
> + ret = 0;
> +
> + return ret;
> +}
> +
> +static int drbg_hmac_process_addtl(struct drbg_state *drbg,
> + unsigned char *addtl_input, size_t addtllen)
> +{
> + struct drbg_conc addtl;
> + DRBG_CLEAR_CONC(addtl);
> + if(0 == addtllen)
> + return 0;
> + addtl.in = addtl_input;
> + addtl.len = addtllen;
> + /* 10.1.2.5 step 2 */
> + return drbg_hmac_update_state(drbg, &addtl, 1);
> +}
> +
> +static int drbg_hmac_preprocess_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst,
> + short *length)
> +{
> + *src = drbg->V;
> + *dst = drbg->V;
> + *length = DRBG_STATELEN(drbg);
> + return 0;
> +}
> +static void drbg_hmac_postprocess_extract(struct drbg_state *drbg,
> + unsigned char *src,
> + unsigned char *dst, int notlast)
> +{
> + /* nothing needed */
> +}
> +
> +static void drbg_hmac_cleanup_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst)
> +{
> + /* nothing needed */
> +}
> +
> +static int drbg_hmac_newstate_postgen(struct drbg_state *drbg,
> + unsigned char *addtl_input,
> + size_t addtllen)
> +{
> + struct drbg_conc addtl;
> + DRBG_CLEAR_CONC(addtl);
> + addtl.in = addtl_input;
> + addtl.len = addtllen;
> + /* 10.1.2.5 step 6 */
> + return drbg_hmac_update_state(drbg, &addtl, 1);
> +}
> +
> +static struct drbg_state_ops drbg_hmac_ops = {
> + .process_addtl = drbg_hmac_process_addtl,
> + .preprocess_extract = drbg_hmac_preprocess_extract,
> + .postprocess_extract = drbg_hmac_postprocess_extract,
> + .cleanup_extract = drbg_hmac_cleanup_extract,
> + .newstate_postgen = drbg_hmac_newstate_postgen,
> + .update_state = drbg_hmac_update_state,
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +
> +/******************************************************************
> + * Hash DRBG callback functions
> + ******************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> +static int drbg_hash_df(struct drbg_state *drbg,
> + unsigned char *outval, size_t outlen,
> + struct drbg_conc *entropy)
> +{
> + int ret = 0;
> + /* 10.1.1.4 step 1 */
> + size_t len = 0;
> + unsigned char tmp[DRBG_HASH_BLK], input[5];
> + struct drbg_conc data1;
> +
> + DRBG_CLEAR_HASH_BLK(tmp);
> + DRBG_CLEAR_CONC(data1);
> +
> + /* 10.4.1 step 3 */
> + input[0] = 1;
> + drbg_int2byte(&input[1], (outlen * 8), 4);
> +
> + /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
> + data1.next = entropy;
> + data1.in = input;
> + data1.len = 5;
> +
> + /* 10.4.1 step 4 */
> + while(len < outlen) {
> + short blocklen = 0;
> + /* 10.4.1 step 4.1 */
> + ret = drbg->core->cipher_fn(drbg, NULL, tmp, &data1);
> + if(ret) {
> + memset(outval, 0, outlen);
> + goto out;
> + }
> + /* 10.4.1 step 4.2 */
> + input[0]++;
> + blocklen = (DRBG_BLOCKLEN(drbg) < (outlen - len)) ?
> + DRBG_BLOCKLEN(drbg) : (outlen - len);
> + memcpy(outval + len, tmp, blocklen);
> + len += blocklen;
> + }
> +
> +out:
> + DRBG_CLEAR_HASH_BLK(tmp);
> + return ret;
> +}
> +
> +static int drbg_hash_update_state(struct drbg_state *drbg,
> + struct drbg_conc *seed,
> + int reseed)
> +{
> + int ret = 0;
> + struct drbg_conc data1, data2;
> + unsigned char V[DRBG_HASH_BLK];
> +
> + DRBG_CLEAR_HASH_BLK(V);
> + DRBG_CLEAR_CONC(data1);
> + DRBG_CLEAR_CONC(data2);
> +
> + if(reseed) {
> + /* 10.1.1.3 step 1: string length is concatenation of
> + * 1 byte, V and seed (which is concatenated entropy/addtl
> + * input)
> + */
> + memcpy(V, drbg->V, DRBG_STATELEN(drbg));
> + data1.next = &data2;
> + data2.next = seed;
> + data1.in = (unsigned char *)"\1";
> + data1.len = 1;
> + data2.in = V;
> + data2.len = DRBG_STATELEN(drbg);
> + } else {
> + data1.in = seed->in;
> + data1.len = seed->len;
> + data1.next = seed->next;
> + }
> +
> + /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
> + ret = drbg_hash_df(drbg, drbg->V, DRBG_STATELEN(drbg), &data1);
> + if(ret)
> + goto out;
> +
> + /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
> + data1.next = &data2;
> + data2.next = NULL;
> + data1.in = (unsigned char *)"\0";
> + data1.len = 1;
> + data2.in = drbg->V;
> + data2.len = DRBG_STATELEN(drbg);
> + /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
> + ret = drbg_hash_df(drbg, drbg->C, DRBG_STATELEN(drbg), &data1);
> +
> +out:
> + DRBG_CLEAR_HASH_BLK(V);
> + return ret;
> +}
> +
> +static int drbg_hash_process_addtl(struct drbg_state *drbg,
> + unsigned char *addtl_input, size_t addtllen)
> +{
> + int ret = 0;
> + unsigned char w[DRBG_HASH_BLK];
> + struct drbg_conc data1, data2, data3;
> +
> + DRBG_CLEAR_HASH_BLK(w);
> + DRBG_CLEAR_CONC(data1);
> + DRBG_CLEAR_CONC(data2);
> + DRBG_CLEAR_CONC(data3);
> +
> + /* 10.1.1.4 step 2 */
> + if(0 == addtllen)
> + return 0;
> +
> + /* 10.1.1.4 step 2a -- concatenation */
> + data1.next = &data2;
> + data2.next = &data3;
> + data1.in = (unsigned char *) "\2";
> + data1.len = 1;
> + data2.in = drbg->V;
> + data2.len = DRBG_STATELEN(drbg);
> + data3.in = addtl_input;
> + data3.len = addtllen;
> + /* 10.1.1.4 step 2a -- cipher invocation */
> + ret = drbg->core->cipher_fn(drbg, NULL, w, &data1);
> + if(ret)
> + goto out;
> +
> + /* 10.1.1.4 step 2b */
> + drbg_add_buf(drbg->V, DRBG_STATELEN(drbg), w, DRBG_BLOCKLEN(drbg));
> +
> +out:
> + DRBG_CLEAR_HASH_BLK(w);
> + return ret;
> +}
> +
> +static int drbg_hash_preprocess_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst,
> + short *length)
> +{
> + memset(drbg->scratchpad, 0,
> + (DRBG_STATELEN(drbg) + DRBG_BLOCKLEN(drbg)));
> + memcpy(drbg->scratchpad, drbg->V, DRBG_STATELEN(drbg));
> +
> + *src = (unsigned char *)drbg->scratchpad;
> + *dst = (unsigned char *)drbg->scratchpad + DRBG_STATELEN(drbg);
> + *length = DRBG_STATELEN(drbg);
> +
> + return 0;
> +}
> +
> +static void drbg_hash_postprocess_extract(struct drbg_state *drbg,
> + unsigned char *src,
> + unsigned char *dst, int notlast)
> +{
> + /* 10.1.1.4 hashgen step 4.3 */
> + if(notlast)
> + drbg_add_buf(src, DRBG_STATELEN(drbg),
> + (unsigned char *) "\1", 1);
> +}
> +
> +static void drbg_hash_cleanup_extract(struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst)
> +{
> + memset(drbg->scratchpad, 0,
> + (DRBG_STATELEN(drbg) + DRBG_BLOCKLEN(drbg)));
> +}
> +
> +static int drbg_hash_newstate_postgen(struct drbg_state *drbg,
> + unsigned char *addtl_input,
> + size_t addtllen)
> +{
> + int ret = 0;
> + unsigned char req[8], H[DRBG_HASH_BLK];
> + struct drbg_conc data1, data2;
> +
> + DRBG_CLEAR_HASH_BLK(H);
> + DRBG_CLEAR_CONC(data1);
> + DRBG_CLEAR_CONC(data2);
> +
> + /* 10.1.1.4 step 4 */
> + data1.next = &data2;
> + data1.in = (unsigned char *) "\3";
> + data1.len = 1;
> + data2.in = drbg->V;
> + data2.len = DRBG_STATELEN(drbg);
> + ret = drbg->core->cipher_fn(drbg, NULL, H, &data1);
> + if(ret)
> + goto out;
> +
> + /* 10.1.1.4 step 5 */
> + drbg_add_buf(drbg->V, DRBG_STATELEN(drbg),
> + H, DRBG_BLOCKLEN(drbg));
> + drbg_add_buf(drbg->V, DRBG_STATELEN(drbg),
> + drbg->C, DRBG_STATELEN(drbg));
> + drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
> + drbg_add_buf(drbg->V, DRBG_STATELEN(drbg), req, 8);
> +
> +out:
> + DRBG_CLEAR_HASH_BLK(H);
> + return ret;
> +}
> +
> +static struct drbg_state_ops drbg_hash_ops = {
> + .process_addtl = drbg_hash_process_addtl,
> + .preprocess_extract = drbg_hash_preprocess_extract,
> + .postprocess_extract = drbg_hash_postprocess_extract,
> + .cleanup_extract = drbg_hash_cleanup_extract,
> + .newstate_postgen = drbg_hash_newstate_postgen,
> + .update_state = drbg_hash_update_state,
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +
> +/******************************************************************
> + * Functions common for DRBG implementations
> + ******************************************************************/
> +
> +/*
> + * Set up the pointers to the right DRBG type implementations
> + *
> + * @drbg DRBG handle
> + *
> + * return:
> + * 0 on success
> + * error value otherwise
> + */
> +static inline int drbg_add_callbacks(struct drbg_state *drbg)
> +{
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> + if(drbg->flags & DRBG_HMAC_MASK) {
> + drbg->d_ops = &drbg_hmac_ops;
> + return 0;
> + }
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> + if(drbg->flags & DRBG_HASH_MASK) {
> + drbg->d_ops = &drbg_hash_ops;
> + return 0;
> + }
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> + if(drbg->flags & DRBG_CTR_MASK) {
> + drbg->d_ops = &drbg_ctr_ops;
> + return 0;
> + }
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> + return -EOPNOTSUPP;
> +}
> +
> +/*
> + * Seeding or reseeding of the DRBG
> + *
> + * @drbg: DRBG state struct
> + * @pers: personalization / additional information buffer
> + * @perslen: size of personalization / additional information buffer
> + * @reseed: 0 for initial seed process, 1 for reseeding
> + *
> + * return:
> + * 0 on success
> + * error value otherwise
> + */
> +static int drbg_seed(struct drbg_state *drbg, unsigned char *pers,
> + size_t perslen, int reseed)
> +{
> + int ret = 0;
> + unsigned char *entropy = NULL;
> + size_t entropylen = 0;
> + struct drbg_conc data1, data2;
> +
> + DRBG_CLEAR_CONC(data1);
> + DRBG_CLEAR_CONC(data2);
> +
> + /* 9.1 / 9.2 / 9.3.1 step 3 */
> + if(perslen > (drbg_max_addtl(drbg)))
> + return -EINVAL;
> +
> + /* section 8.6.1 together with section 8.6.3 and 8.6.7 -- consider DRBG
> + * seeded only when sufficient seed is provided */
> + /* Sufficient seed is provided: when we have no derivation function,
> + * a nonce is not necessary, if we have a derivation function, a nonce
> + * is necessary. A nonce must be at least 1/2 of the security strength
> + * of the DRBG in size. Thus, entropy * nonce is 3/2 of the strength.
> + *
> + * The consideration of a nonce is only applicable during initial
> + * seeding.
> + */
> +
> + /* chapter 9: No seed is provided, the DRBG shall get its own seed */
> + if(drbg->test_data) {
> + data1.in = drbg->test_data->testentropy;
> + data1.len = drbg->test_data->testentropylen;
> + } else {
> + entropylen = (drbg_sec_strength(drbg->flags) / 8);
> + if(0 == reseed)
> + /* make sure we round up strength/2 in
> + * case it is not divisible by 2 */
> + entropylen = ((entropylen + 1) / 2) * 3;
> +
> + entropy = kzalloc(entropylen, GFP_KERNEL);
> + if(!entropy)
> + return -ENOMEM;
> + get_random_bytes(entropy, entropylen);
> + data1.in = entropy;
> + data1.len = entropylen;
> + }
> +
> + /* 10.1.1.2 step 1 and 10.1.1.3 step 1 (concatenation of entropy /
> + * addtl input) */
> + if(0 < perslen) {
> + data1.next = &data2;
> + data2.in = pers;
> + data2.len = perslen;
> + }
> +
> + ret = drbg->d_ops->update_state(drbg, &data1, reseed);
> + if(ret)
> + goto out;
> +
> + drbg->flags &= ~(DRBG_UNSEEDED);
> + /* 10.1.1.2 / 10.1.1.3 step 5 */
> + drbg->reseed_ctr = 1;
> +
> +out:
> + if (entropy)
> + kzfree(entropy);
> + return ret;
> +}
> +
> +/*
> + * Check for reseeding of the DRBG and invoke reseeding if necessary.
> + * This includes the enforcement of the prediction resistance as well
> + * as the reseeding constraint set by the SP800-90A requirement.
> + *
> + * @drbg: DRBG state struct
> + * @addtl_input: addition input for reseeding
> + * @addtllen: length of additional input
> + *
> + * return:
> + * 0 on success -- implies a successful reseeding of the DRBG handle
> + * error value otherwise
> + */
> +static int drbg_check_reseed(struct drbg_state *drbg,
> + unsigned char **addtl_input, size_t *addtllen)
> +{
> + int ret = 0;
> +
> + if((drbg_max_requests(drbg)) < drbg->reseed_ctr)
> + drbg->flags |= DRBG_UNSEEDED;
> +
> + /* section 9.3.1 step 6 and 7 */
> + if(!(drbg->flags & DRBG_PREDICTION_RESIST) &&
> + !(drbg->flags & DRBG_UNSEEDED))
> + return 0;
> + ret = drbg_seed(drbg, *addtl_input, *addtllen, 1);
> +
> + /* This is NOT documented, but needed! */
> + *addtl_input = NULL;
> + *addtllen = 0;
> +
> + return ret;
> +}
> +
> +/*
> + * Sanity check of state during drbg_generate() -- we check for:
> + * reseeding requirement
> + * maximum number of requested bits
> + *
> + * @drbg: DRBG state struct
> + * @strength: requested minimum strength of DRBG
> + * @buflen: size of requested random number
> + *
> + * return:
> + * 0 on success
> + * error value otherwise
> + */
> +static inline int drbg_generate_sanity(struct drbg_state *drbg, size_t buflen,
> + unsigned char *pers, size_t perslen)
> +{
> + if(NULL == drbg)
> + return -EINVAL;
> + if(NULL == drbg->core)
> + return -EINVAL;
> + if(NULL == drbg->V)
> + return -EINVAL;
> + if(NULL == drbg->C)
> + return -EINVAL;
> + if(NULL == drbg->scratchpad)
> + return -EINVAL;
> +
> + /* 9.1 / 9.2 / 9.3.1 step 3 */
> + if(perslen > (drbg_max_addtl(drbg)))
> + return -EINVAL;
> + if(NULL == pers && 0 < perslen)
> + return -EINVAL;
> +
> + /* 9.3.1 step 2 -- max_bits is in bits, but buflen is in bytes */
> + if(buflen > (drbg_max_request_bytes(drbg)))
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +/*
> + * FIPS 140-2 continuous self test
> + * The test is performed on the result of one round of the output
> + * function. Thus, the function implicitly knows the size of the
> + * buffer.
> + *
> + * @drbg DRBG handle
> + * @buf output buffer of random data to be checked
> + *
> + * return:
> + * true on success
> + * false on error
> + */
> +static bool drbg_fips_continuous_test(struct drbg_state *drbg,
> + unsigned char *buf)
> +{
> +#ifdef CONFIG_CRYPTO_FIPS
> + int ret = 0;
> + /* skip test if we test the overall system */
> + if(drbg->test_data)
> + return true;
> + /* only perform test in FIPS mode */
> + if(0 == fips_enabled)
> + return true;
> + if(!drbg->prev) {
> + drbg->prev = kzalloc(DRBG_BLOCKLEN(drbg), GFP_KERNEL);
> + if(!drbg->prev)
> + return -ENOMEM;
> + /* Priming of FIPS test */
> + memcpy(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
> + /* return false due to priming, i.e. another round is needed */
> + return false;
> + }
> + ret = memcmp(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
> + memcpy(drbg->prev, buf, DRBG_BLOCKLEN(drbg));
> + /* invert the memcmp result, because the test shall pass when the
> + * two compared values do not match */
> + if(ret)
> + return true;
> + else
> + return false;
> +#else
> + return true;
> +#endif /* CONFIG_CRYPTO_FIPS */
> +}
> +
> +/*
> + * Heavy lifting function of generating random numbers by generating
> + * blockwise output via cipher and ensuring that the last block is truncated
> + * to the proper length.
> + *
> + * @drbg DRBG handle
> + * @buf output buffer of random data
> + * @buflen length of output buffer
> + *
> + * return: generated bytes
> + */
> +static unsigned int drbg_extract_bytes(struct drbg_state *drbg,
> + unsigned char *buf,
> + unsigned int buflen)
> +{
> + int ret = 0;
> + /* 10.1.1.4 step 1 */
> + unsigned int len = 0;
> + unsigned char *src = NULL;
> + unsigned char *dst = NULL;
> + short length = 0;
> + struct drbg_conc data;
> +
> + DRBG_CLEAR_CONC(data);
> +
> + /* set up the source buffers and destination buffers as needed for
> + * the DRBG type -- the source buffer is fed into the cipher operation
> + * and the destination buffer will hold the result of the cipher
> + * operation */
> + ret = drbg->d_ops->preprocess_extract(drbg, &src, &dst, &length);
> + if(ret)
> + return 0;
> + data.in = src;
> + data.len = length;
> +
> + /* potential integer overflow is covered by drbg_generate_sanity which
> + * ensures that buflen cannot overflow a signed int */
> + while(len < buflen) {
> + unsigned int outlen = 0;
> + /* 10.1.1.4 step hashgen 4.1, 10.1.2.5 step 4.1,
> + * 10.2.1.5.2 step 4.2 */
> + ret = drbg->core->cipher_fn(drbg, drbg->C, dst, &data);
> + if(ret)
> + goto out;
> + outlen = (DRBG_BLOCKLEN(drbg) < (buflen - len)) ?
> + DRBG_BLOCKLEN(drbg) : (buflen - len);
> + if(!drbg_fips_continuous_test(drbg, dst)) {
> + /* Continuous test failed or is just primed -- generate
> + * next round without copying the generated value out
> + * to the caller -- potential for a deadlock, but
> + * this error cannot mathematically occur. If it
> + * occurs, the integrity of the entire kernel is
> + * lost. */
> + drbg->d_ops->postprocess_extract(drbg, src, dst,
> + (len < buflen));
> + continue;
> + }
> + /* 10.1.1.4 step hashgen 4.2, 10.1.2.5 step 4.2,
> + * 10.2.1.5.2 step 4.3 */
> + memcpy(buf + len, dst, outlen);
> + len += outlen;
> + /* Advance the buffers, if needed by the DRBG type */
> + drbg->d_ops->postprocess_extract(drbg, src, dst,
> + (len < buflen));
> + }
> +
> +out:
> + /* Allow DRBG type implementations to cleanup any temporary buffers
> + * set up when defining source and destination buffers
> + */
> + drbg->d_ops->cleanup_extract(drbg, &src, &dst);
> + return len;
> +}
> +
> +/*
> + * Process request to generate random numbers. This function ensures
> + * that the additional information / personalization string is processed
> + * before bytes are generated. Also, this function ensures that the DRBG
> + * state is updated after random number generation.
> + *
> + * @drbg DRBG handle
> + * @buf output buffer of random data
> + * @buflen length of output buffer
> + * @addtl_input Additional input / personalization string buffer
> + * @addtllen Length of additional input buffer
> + *
> + * return: generated bytes
> + */
> +static unsigned int drbg_generate_bytes(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + unsigned char *addtl_input,
> + size_t addtllen)
> +{
> + unsigned int len = 0;
> +
> + /* 10.1.1.4 step 2, 10.1.2.5 step 2, 10.2.1.5.2 step 2 */
> + if(drbg->d_ops->process_addtl(drbg, addtl_input, addtllen))
> + return 0;
> + /* 10.1.1.4 step 3, 10.1.2.5 step 3, 10.2.1.5.2 step 3 */
> + len = drbg_extract_bytes(drbg, buf, buflen);
> +
> + /* 10.1.1.4 step 4 and following, 10.1.2.5 step 6, 10.2.1.5.2 step 6 */
> + if(drbg->d_ops->newstate_postgen(drbg, addtl_input, addtllen))
> + return 0;
> + return len;
> +}
> +
> +/*
> + * Check for programming errors: ensure that stack variable size is
> + * sufficient for ciphers.
> + *
> + * @flags flags specifying the core cipher type
> + * @core selected core
> + *
> + * return:
> + * true if sanity check passed
> + * false if sanity check failed
> + */
> +static inline bool drbg_check_progamming_sanity(drbg_flag_t flags,
> + const struct drbg_core *core)
> +{
> + size_t size = 0;
> + if(flags & DRBG_CTR_MASK)
> + size = DRBG_CTR_BLK;
> + else if (flags & DRBG_HASH_MASK)
> + size = DRBG_HASH_BLK;
> + else if (flags & DRBG_HMAC_MASK)
> + size = DRBG_HMAC_BLK;
> + return (size >= core->statelen);
> +}
> +
> +/*
> + * Find the right cipher callback data structure that matches the
> + * the requested cipher type. The code returns the first match in case caller
> + * made the error to request multiple ciphers
> + *
> + * @flags Flags handed in by caller during instantiation request
> + *
> + * return:
> + * pointer to core on success
> + * NULL on error
> + */
> +static const inline struct drbg_core *drbg_find_core(drbg_flag_t flags)
> +{
> + drbg_flag_t req_cipher = (flags & DRBG_CIPHER_MASK);
> + int i = 0;
> +
> + for(i = 0; ARRAY_SIZE(cores) > i; i++) {
> + if(req_cipher & cores[i].flags) {
> + if(drbg_check_progamming_sanity(req_cipher, &cores[i]))
> + return &cores[i];
> + return NULL;
> + }
> + }
> + return NULL;
> +}
> +
> +/*************************************************************************
> + * DRBG interface functions
> + *************************************************************************/
> +
> +/*
> + * DRBG instantiation function as required by SP800-90A - this function
> + * sets up the DRBG handle, performs the initial seeding and all sanity
> + * checks required by SP800-90A
> + *
> + * @drbg memory of state -- if NULL, new memory is allocated
> + * @pers Personalization string that is mixed into state, may be NULL -- note
> + * the entropy is pulled by the DRBG internally unconditionally
> + * as defined in SP800-90A. The additional input is mixed into
> + * the state in addition to the pulled entropy.
> + * @perslen Length of personalization string buffer, shall be 0 when buffer
> + * is NULL
> + * @flags Flags defining the requested DRBG type and cipher type. The flags
> + * are defined in drbg.h and may be XORed. Beware, if you XOR multiple
> + * cipher types together, the code picks the core on a first come first
> + * serve basis as it iterates through the available cipher cores and
> + * uses the one with the first match. The minimum required flags are:
> + * cipher type flag
> + *
> + * return
> + * 0 on success
> + * error value otherwise
> + */
> +
> +static int drbg_instantiate(struct drbg_state *drbg,
> + unsigned char *pers, size_t perslen,
> + drbg_flag_t flags)
> +{
> + int ret = -ENOMEM;
> + const struct drbg_core *core = NULL;
> +
> + core = drbg_find_core(flags);
> + if(NULL == core)
> + return -EINVAL;
> +
> + /* 9.1 step 1 is implicit with the selected DRBG type -- see
> + * drbg_sec_strength() */
> +
> + /* 9.1 step 2 is implicit as caller can select prediction resistance
> + * and the flag is copied into drbg->flags --
> + * all DRBG types support prediction resistance */
> +
> + /* 9.1 step 4 is implicit in drbg_sec_strength */
> +
> + /* no allocation of drbg as this is done by the kernel crypto API */
> + drbg->V = kzalloc(core->statelen, GFP_KERNEL);
> + if(!drbg->V)
> + goto err;
> + drbg->C = kzalloc(core->statelen, GFP_KERNEL);
> + if(!drbg->C)
> + goto err;
> +
> + /* the Hash DRBG needs full buffer, CTR needs only blocklen_bytes and
> + * HMAC does not need buffer at all */
> + drbg->scratchpad = kzalloc(core->statelen + core->blocklen_bytes,
> + GFP_KERNEL);
> + if(!drbg->scratchpad)
> + goto err;
> +
> + spin_lock_init(&drbg->drbg_lock);
> +
> + drbg->flags = flags;
> + drbg->flags |= DRBG_UNSEEDED;
> + drbg->core = core;
> +
> + if(core->init_lib)
> + if(core->init_lib(drbg))
> + return -EFAULT;
> +
> + ret = drbg_add_callbacks(drbg);
> + if(ret)
> + goto err;
> +
> + /* 9.1 step 6 through 11 */
> + ret = drbg_seed(drbg, pers, perslen, 0);
> + if(ret)
> + goto err;
> +
> + return 0;
> +
> +err:
> + if(drbg->C)
> + kzfree(drbg->C);
> + drbg->C = NULL;
> + if(drbg->V)
> + kzfree(drbg->V);
> + drbg->V = NULL;
> + if(drbg->scratchpad)
> + kzfree(drbg->scratchpad);
> + drbg->scratchpad = NULL;
> + return ret;
> +}
> +
> +/*
> + * DRBG uninstantiate function as required by SP800-90A - this function
> + * frees all buffers and the DRBG handle
> + *
> + * @drbg DRBG state handle
> + * @free_state free the DRBG state handle in addition to zeroization
> + *
> + * return
> + * 0 on success
> + */
> +static int drbg_uninstantiate(struct drbg_state *drbg)
> +{
> + /* ensure that other threads have their chance to complete their work */
> + spin_lock_bh(&drbg->drbg_lock);
> + if(drbg->core->fini_lib)
> + drbg->core->fini_lib(drbg);
> + if(drbg->V)
> + kzfree(drbg->V);
> + drbg->V = NULL;
> + if(drbg->C)
> + kzfree(drbg->C);
> + drbg->C = NULL;
> + if(drbg->scratchpad)
> + kzfree(drbg->scratchpad);
> + drbg->scratchpad = NULL;
> +#ifdef CONFIG_CRYPTO_FIPS
> + if(drbg->prev)
> + kzfree(drbg->prev);
> + drbg->prev = NULL;
> +#endif
> + /* no scrubbing of test_data -- this shall survive an uninstantiate */
> + spin_unlock_bh(&drbg->drbg_lock);
> + /* no freeing of drbg as this is done by the kernel crypto API */
> + return 0;
> +}
> +
> +/*
> + * DRBG generate function as required by SP800-90A - this function
> + * generates random numbers
> + *
> + * @drbg DRBG state handle
> + * @buf Buffer where to store the random numbers -- the buffer must already
> + * be pre-allocated by caller
> + * @buflen Length of output buffer - this value defines the number of random
> + * bytes pulled from DRBG
> + * @addtl_input Additional input that is mixed into state, may be NULL -- note
> + * the entropy is pulled by the DRBG internally unconditionally
> + * as defined in SP800-90A. The additional input is mixed into
> + * the state in addition to the pulled entropy.
> + * @addtllen Length of additional input buffer, shall be 0 when buffer is NULL
> + *
> + * return: generated number of bytes
> + */
> +static unsigned int drbg_generate(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + unsigned char *addtl_input, size_t addtllen)
> +{
> + unsigned int len = 0;
> +
> + if(0 == buflen)
> + return 0;
> +
> + spin_lock_bh(&drbg->drbg_lock);
> + if(drbg_generate_sanity(drbg, buflen, addtl_input, addtllen))
> + goto out;
> +
> + if(drbg_check_reseed(drbg, &addtl_input, &addtllen))
> + goto out;
> +
> + len = drbg_generate_bytes(drbg, buf, buflen, addtl_input, addtllen);
> +
> + /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
> + drbg->reseed_ctr++;
> +
> +out:
> + spin_unlock_bh(&drbg->drbg_lock);
> + return len;
> +}
> +
> +/*
> + * DRBG reseed function as required by SP800-90A
> + *
> + * @drbg DRBG state handle
> + * @addtl_input Additional input that is mixed into state, may be NULL -- note
> + * the entropy is pulled by the DRBG internally unconditionally
> + * as defined in SP800-90A. The additional input is mixed into
> + * the state in addition to the pulled entropy.
> + * @addtllen Length of additional input buffer, shall be 0 when buffer is NULL
> + *
> + * return
> + * 0 on success
> + * error value otherwise
> + */
> +/* The kernel crypto API does not implement a reseeding function API call.
> + * This function should be enabled once a reseeding API call is implemented.
> + */
> +#if 0
> +static int drbg_reseed(struct drbg_state *drbg, unsigned char *addtl_input,
> + size_t addtllen)
> +{
> + int ret = 0;
> + spin_lock_bh(&drbg->drbg_lock);
> + ret = drbg_seed(drbg, addtl_input, addtllen, 1);
> + spin_unlock_bh(&drbg->drbg_lock);
> + return ret;
> +}
> +#endif
> +
> +/*
> + * Helper function for setting the test data in the DRBG
> + *
> + * @drbg DRBG state handle
> + * @test_data test data to sets
> + */
> +static inline void drbg_set_testdata(struct drbg_state *drbg,
> + struct drbg_test_data *test_data)
> +{
> + if(!test_data)
> + return;
> + spin_lock_bh(&drbg->drbg_lock);
> + drbg->test_data = test_data;
> + spin_unlock_bh(&drbg->drbg_lock);
> +}
> +
> +/***************************************************************
> + * Kernel crypto APi cipher invocations requested by DRBG
> + ***************************************************************/
> +
> +#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
> +static int drbg_init_hash_kernel(struct drbg_state *drbg)
> +{
> + int ret = 0;
> + struct shash_desc *shash;
> + int size;
> + struct crypto_shash *tfm;
> +
> + /* allocate synchronous hash */
> + tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
> + if (IS_ERR(tfm)) {
> + printk("drbg: could not allocate digest TFM handle\n");
> + return -EFAULT;
> + }
> +
> + size = sizeof(struct shash_desc);
> + shash = kzalloc(size, GFP_KERNEL);
> + if (!shash) {
> + crypto_free_shash(tfm);
> + return -ENOMEM;
> + }
> + shash->tfm = tfm;
> + shash->flags = 0x0;
> + drbg->priv_data = shash;
> +
> + return ret;
> +}
> +
> +static int drbg_fini_hash_kernel(struct drbg_state *drbg)
> +{
> + struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
> + if(shash) {
> + crypto_free_shash(shash->tfm);
> + kzfree(shash);
> + }
> + drbg->priv_data = NULL;
> + return 0;
> +}
> +
> +static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in)
> +{
> + struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
> + crypto_shash_init(shash);
> + for(; NULL != in; in = in->next)
> + crypto_shash_update(shash, in->in, in->len);
> + return crypto_shash_final(shash, outval);
> +}
> +#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +static int drbg_kcapi_hmac(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in)
> +{
> + int ret = 0;
> + struct shash_desc *shash = (struct shash_desc *)drbg->priv_data;
> + ret = crypto_shash_setkey(shash->tfm, key, DRBG_STATELEN(drbg));
> + if(ret)
> + return ret;
> + return drbg_kcapi_hash(drbg, key, outval, in);
> +}
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_init_sym_kernel(struct drbg_state *drbg)
> +{
> + int ret = 0;
> + struct blkcipher_desc *desc;
> + struct crypto_blkcipher *blkcipher;
> +
> + /* allocate synchronous cipher */
> + blkcipher = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
> + if(IS_ERR(blkcipher)) {
> + printk("drbg: could not allocate cipher TFM handle\n");
> + return -EFAULT;
> + }
> +
> + desc = kzalloc(sizeof(struct blkcipher_desc), GFP_KERNEL);
> + if (!desc) {
> + crypto_free_blkcipher(blkcipher);
> + return -ENOMEM;
> + }
> + desc->tfm = blkcipher;
> + desc->flags = 0;
> + drbg->priv_data = desc;
> +
> + return ret;
> +}
> +
> +static int drbg_fini_sym_kernel(struct drbg_state *drbg)
> +{
> + struct blkcipher_desc *desc =
> + (struct blkcipher_desc *)drbg->priv_data;
> + if(desc) {
> + crypto_free_blkcipher(desc->tfm);
> + kzfree(desc);
> + }
> + drbg->priv_data = NULL;
> + return 0;
> +}
> +
> +static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in)
> +{
> + int ret = 0;
> + struct scatterlist sg_in, sg_out;
> + struct blkcipher_desc *desc =
> + (struct blkcipher_desc *)drbg->priv_data;
> +
> + if(crypto_blkcipher_setkey(desc->tfm, key, (DRBG_KEYLEN(drbg))))
> + return -EFAULT;
> + /* in is only component */
> + sg_init_one(&sg_in, in->in, in->len);
> + sg_init_one(&sg_out, outval, DRBG_BLOCKLEN(drbg));
> + ret = crypto_blkcipher_encrypt(desc, &sg_out, &sg_in, in->len);
> +
> + return ret;
> +}
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +
> +/***************************************************************
> + * Kernel crypto API interface to register DRBG
> + ***************************************************************/
> +
> +/*
> + * Look up the DRBG flags by given kernel crypto API cra_name
> + * The code uses the cores definition to do this
> + *
> + * @cra_name kernel crypto API cra_name
> + *
> + * return: flags
> + */
> +static drbg_flag_t drbg_convert_tfm_flags(const char *cra_name)
> +{
> + int i = 0;
> + size_t start = 0;
> + int len = 0;
> + drbg_flag_t pr_flag = DRBG_PREDICTION_RESIST;
> +
> + /* disassemble the names */
> + if(0 == memcmp(cra_name, "drbg(nopr(", 10)) {
> + start = 10;
> + pr_flag = 0;
> + } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
> + start = 8;
> + } else
> + return 0;
> +
> + /* remove the first part and the closing parenthesis */
> + len = strlen(cra_name) - start - 2;
> +
> + for(i = 0; ARRAY_SIZE(cores) > i; i++) {
> + if(0 == memcmp(cra_name + start, cores[i].cra_name, len))
> + /* add the prediction resistance flag, if drbg(pr(()))
> + * is selected */
> + return (cores[i].flags | pr_flag);
> + }
> + return 0;
> +}
> +
> +/*
> + * Initialize one DRBG invoked by the kernel crypto API
> + *
> + * Function uses the kernel crypto API cra_name to look up
> + * the flags to instantiate the DRBG
> + */
> +static int drbg_kcapi_init(struct crypto_tfm *tfm)
> +{
> + struct drbg_state *drbg = crypto_tfm_ctx(tfm);
> + drbg_flag_t flags = 0;
> +
> + flags = drbg_convert_tfm_flags(crypto_tfm_alg_name(tfm));
> + /* when personalization string is needed, the caller must call reset
> + * and provide the personalization string as seed information */
> + return drbg_instantiate(drbg, NULL, 0, flags);
> +}
> +
> +static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
> +{
> + drbg_uninstantiate(crypto_tfm_ctx(tfm));
> +}
> +
> +/*
> + * Generate random numbers:
> + * The API of the kernel crypto API is extended as follows:
> + *
> + * If dlen is larger than zero, rdata is interpreted as the output buffer
> + * where random data is to be stored.
> + *
> + * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
> + * which holds the additional information string that is used for the
> + * DRBG generation process. The output buffer that is to be used to store
> + * data is also pointed to by struct drbg_gen.
> + *
> + */
> +static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
> + unsigned int dlen)
> +{
> + struct drbg_state *drbg = crypto_rng_ctx(tfm);
> + if(0 < dlen) {
> + return drbg_generate(drbg, rdata, dlen,
> + NULL, 0);
> + } else {
> + struct drbg_gen *data = (struct drbg_gen *)rdata;
> + drbg_set_testdata(drbg, data->test_data);
> + return drbg_generate(drbg, data->outbuf, data->outlen,
> + data->addtl_input, data->addtllen);
> + }
> +}
> +
> +static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
> +{
> + struct drbg_state *drbg = crypto_rng_ctx(tfm);
> + struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
> + drbg_flag_t flags = 0;
> +
> + drbg_uninstantiate(drbg);
> + flags = drbg_convert_tfm_flags(crypto_tfm_alg_name(tfm_base));
> + if(0 < slen) {
> + return drbg_instantiate(drbg, seed, slen, flags);
> + } else {
> + struct drbg_gen *data = (struct drbg_gen *)seed;
> + drbg_set_testdata(drbg, data->test_data);
> + return drbg_instantiate(drbg, data->addtl_input, data->addtllen,
> + flags);
> + }
> +}
> +
> +/***************************************************************
> + * Kernel module: code to load the module
> + ***************************************************************/
> +
> +static struct crypto_alg drbg_algs[22];
> +
> +/*
> + * Fill the array drbg_algs used to register the different DRBGs
> + * with the kernel crypto API. To fill the array, the information
> + * from cores[] is used.
> + */
> +static void __init drbg_fill_array(unsigned long i, unsigned long j, int pr)
> +{
> + int pos = 0;
> +
> + memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
> + if(pr) {
> + memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
> + memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
> + pos = 8;
> + } else {
> + memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
> + memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
> + pos = 10;
> + }
> + memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
> + strlen(cores[j].cra_name));
> + memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))", 2);
> + memcpy(drbg_algs[i].cra_driver_name + pos,
> + cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
> + drbg_algs[i].cra_priority = 100;
> + drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
> + drbg_algs[i].cra_ctxsize= sizeof(struct drbg_state);
> + drbg_algs[i].cra_type = &crypto_rng_type;
> + drbg_algs[i].cra_module = THIS_MODULE;
> + drbg_algs[i].cra_init = drbg_kcapi_init;
> + drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
> + drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
> + drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
> + drbg_algs[i].cra_u.rng.seedsize = 0;
> +}
> +
> +static void __init drbg_create_algs(void)
> +{
> + unsigned int i = 0; /* pointer to drbg_algs */
> + unsigned int j = 0; /* pointer to cores */
> +
> + if(ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
> + printk("drbg: Not all available DRBGs registered (slots needed:"
> + "%lu, slots available: %lu)\n",
> + ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
> +
> + /* each DRBG definition can be used with PR and without PR, thus
> + * we instantiate each DRBG in cores[] twice */
> + for(j = 0; ARRAY_SIZE(cores) > j; j++) {
> + drbg_fill_array(i, j, 1);
> + i++;
> + drbg_fill_array(i, j, 0);
> + i++;
> + }
> +}
> +
> +static int __init drbg_init(void)
> +{
> + drbg_create_algs();
> + return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
> +}
> +
> +void __exit drbg_exit(void)
> +{
> + crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
> +}
> +
> +module_init(drbg_init);
> +module_exit(drbg_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Stephan Mueller <[email protected]>");
> +MODULE_DESCRIPTION("NIST SP800-90A Determinist Random Bit Generator (DRBG) using following cores:"
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +"HMAC "
> +#endif
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> +"Hash "
> +#endif
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +"CTR"
> +#endif
> +);
> +
> --
> 1.8.5.3
>
Stephan,
here are my findings for this patch:
* CodingStyle:
- You have to observe what goes written in Documentation/CodingStyle
special emphasis on, but not only restricted to, function-versus-keyword
space usage.
* scheduling while atomic BUGs:
- suspicious spinlock protection around callsites to crypto api callbacks:
Unless you can guarantee those callbacks do not conditionally call the
scheduler, you'll hit racy bugs on the wild world for sure;
- drbg_fips_continous_test(): you _cannot_ perform non-atomic
allocations within an atomic section, this is a real BUG and it will bite
you sooner or later;
* spin_lock_bh abusive usage @ drbg_generate():
- you hold the spinlock (with disabled IRQs) for a rather too big
critical section, even across several function calls, and this
should be avoided at all costs. You really should refactor you
spinlock crit sects to only grab the lock for a couple few lines
of _machine_ code.
Overall impressions: your code is quite difficult to follow (and it will
be potentially hard to maintain and debug, if merged as it sits) due to
that indirection model chosen to split the implementation of DRBGs
across several tiny functions. Doing that much of callbacks is very
costly and it's not optimal for kernel code, as it causes unnecessary
register thrashing.
By reading the specs, one can conclude you could only use two callbacks
(one for the generate function and another for the (re)seed function)
and get the rest of particular stuff for each drbg implementation all inlined.
Regards,
-- Rafael
On Sun, Mar 09, 2014 at 12:46:42AM +0100, Stephan Mueller wrote:
> The header file includes the definition of:
>
> * DRBG data structures with
> - struct drbg_state as main structure
> - struct drbg_core referencing the backend ciphers
> - struct drbg_state_ops callbach handlers for specific code
> supporting the Hash, HMAC, CTR DRBG implementations
> - struct drbg_conc defining a linked list for input data
> - struct drbg_test_data holding the test "entropy" data for CAVS
> testing and testmgr.c
> - struct drbg_gen allowing test data, additional information
> string and personalization string data to be funneled through
> the kernel crypto API -- the DRBG requires additional
> parameters when invoking the reset and random number
> generation requests than intended by the kernel crypto API
>
> * wrapper function to the kernel crypto API functions using struct
> drbg_gen to pass through all data needed for DRBG
>
> * wrapper functions to kernel crypto API functions usable for testing
> code to inject test_data into the DRBG as needed by CAVS testing and
> testmgr.c.
>
> * DRBG flags required for the operation of the DRBG and for selecting
> the particular DRBG type and backend cipher
>
> * getter functions for data from struct drbg_core
>
> Signed-off-by: Stephan Mueller <[email protected]>
>
> create mode 100644 include/crypto/drbg.h
>
> diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
> new file mode 100644
> index 0000000..16515f9
> --- /dev/null
> +++ b/include/crypto/drbg.h
> @@ -0,0 +1,340 @@
> +/*
> + * DRBG based on NIST SP800-90A
> + *
> + * Copyright Stephan Mueller <[email protected]>, 2014
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, and the entire permission notice in its entirety,
> + * including the disclaimer of warranties.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote
> + * products derived from this software without specific prior
> + * written permission.
> + *
> + * ALTERNATIVELY, this product may be distributed under the terms of
> + * the GNU General Public License, in which case the provisions of the GPL are
> + * required INSTEAD OF the above restrictions. (This clause is
> + * necessary due to a potential bad interaction between the GPL and
> + * the restrictions contained in a BSD-style copyright.)
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + */
> +
> +#ifndef _DRBG_H
> +#define _DRBG_H
> +
> +
> +#include <linux/random.h>
> +#include <linux/scatterlist.h>
> +#include <crypto/hash.h>
> +#include <linux/module.h>
> +#include <linux/crypto.h>
> +#include <linux/slab.h> /* needed for kzalloc */
> +#include <crypto/internal/rng.h>
> +#include <crypto/rng.h>
> +#include <linux/fips.h>
> +#include <linux/spinlock.h>
> +
> +/*
> + * Concatenation Helper
> + *
> + * SP800-90A requires the concatenation of different data. To avoid copying
> + * buffers around or allocate additional memory, the following data structure
> + * is used to point to the original memory with its size. In addition, it
> + * is used to build a linked list. The linked list defines the concatenation
> + * of individual buffers. The order of memory block referenced in that
> + * linked list determines the order of concatenation.
> + */
> +
> +struct drbg_conc
> +{
> + unsigned char *in;
> + size_t len;
> + struct drbg_conc *next;
> +};
> +
> +#define DRBG_CLEAR_CONC(x) \
> + x.in = NULL; \
> + x.len = 0; \
> + x.next = NULL;
> +
Please, consider getting rid of these ugly preprocessor macros and use static
inline functions instead. It not only is much better for maintainability,
but also helps a lot on strong typechecking and can avoid nasty bugs in the future.
> +struct drbg_state;
> +typedef uint32_t drbg_flag_t;
> +
> +struct drbg_core
> +{
> + drbg_flag_t flags; /* flags for the cipher */
> + __u8 statelen; /* maximum state length */
> + __u8 max_addtllen; /* maximum length of personalization string or
> + additional input string -- exponent for base
> + 2 */
> + __u8 max_bits; /* maximum bits per RNG request -- exponent for
> + base 2*/
> + __u8 max_req; /* maximum number of requests -- exponent for
> + base 2 */
> + __u8 blocklen_bytes; /* block size of output in bytes */
> + char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
> + char cra_driver_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto
> + * API */
> + char backend_cra_name[CRYPTO_MAX_ALG_NAME]; /* kernel crypto API
> + * backend cipher name */
> + int (*cipher_fn) (struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_conc *in);
> + int (*init_lib) (struct drbg_state *drbg);
> + int (*fini_lib) (struct drbg_state *drbg);
> +
> +};
> +
> +struct drbg_state_ops
> +{
> + int (*process_addtl) (struct drbg_state *drbg,
> + unsigned char *addtl_input, size_t addtllen);
> + int (*preprocess_extract) (struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst, short *length);
> + void (*postprocess_extract) (struct drbg_state *drbg,
> + unsigned char *src,
> + unsigned char *dst, int notlast);
> + void (*cleanup_extract) (struct drbg_state *drbg,
> + unsigned char **src,
> + unsigned char **dst);
> + int (*newstate_postgen) (struct drbg_state *drbg,
> + unsigned char *addtl_input,
> + size_t addtllen);
> + int (*update_state) (struct drbg_state *drbg, struct drbg_conc *seed,
> + int reseed);
> +};
> +
> +struct drbg_test_data
> +{
> + unsigned char *testentropy; /* TEST PARAMETER: test entropy */
> + size_t testentropylen; /* TEST PARAMETER: length of test entropy */
> +};
> +
> +/* use stack for variables instead of heap */
I would strongly discourage you to keep carving up that much of kernel stack
space for each block descriptor you use, specially if you're planning to
stick with that split across several callbacks implementation you have.
> +#define DRBG_CTR_BLK 48
> +#define DRBG_HASH_BLK 111
> +#define DRBG_HMAC_BLK 64
> +#define DRBG_CLEAR_CTR_BLK(x) memset(x, 0, DRBG_CTR_BLK);
> +#define DRBG_CLEAR_HASH_BLK(x) memset(x, 0, DRBG_HASH_BLK);
> +#define DRBG_CLEAR_HMAC_BLK(x) memset(x, 0, DRBG_HMAC_BLK);
ditto (get rid of these macros, please)
> +
> +#define CLEAR_CRA_NAME(x) memset(x, 0, CRYPTO_MAX_ALG_NAME)
> +
> +struct drbg_state
> +{
> + drbg_flag_t flags; /* Security strength */
> + spinlock_t drbg_lock; /* lock around DRBG */
> + unsigned char *V; /* internal state 10.1.1.1 1a) */
> + unsigned char *C; /* hash: static value 10.1.1.1 1b)
> + * hmac: key */
> + size_t reseed_ctr; /* Number of RNG requests since last reseed --
> + * 10.1.1.1 1c) */
> + unsigned char *scratchpad; /* some memory the DRBG can use for its
> + * operation -- allocated during init */
> + void *priv_data; /* Data needed for specific cipher
> + * implementation */
> +#ifdef CONFIG_CRYPTO_FIPS
> + unsigned char *prev; /* previous output value of DRBG_BLOCKLEN for
> + * FIPS 140-2 continuous test */
> +#endif
> + struct drbg_state_ops *d_ops;
> + const struct drbg_core *core;
> + struct drbg_test_data *test_data;
> +};
> +
> +/* kernel crypto API input data structure for DRBG generate in case dlen
> + * is set to 0 */
> +struct drbg_gen
> +{
> + unsigned char *outbuf; /* output buffer for random numbers */
> + unsigned int outlen; /* size of output buffer */
> + unsigned char *addtl_input; /* input buffer for
> + * additional information string */
> + unsigned int addtllen; /* length of addtl_input */
> + struct drbg_test_data *test_data; /* test data */
> +};
> +
> +/*
> + * This is a wrapper to the kernel crypto API function of
> + * crypto_rng_get_bytes() to allow the caller to provide additional data
> + *
> + * @drng DRBG handle -- see crypto_rng_get_bytes
> + * @outbuf output buffer -- see crypto_rng_get_bytes
> + * @outlen length of output buffer -- see crypto_rng_get_bytes
> + * @addtl_input additional information string input buffer
> + * @addtllen length of additional information string buffer
> + *
> + * return
> + * see crypto_rng_get_bytes
> + */
> +static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
> + unsigned char *outbuf, unsigned int outlen,
> + unsigned char *addtl_input, size_t addtllen)
> +{
> + int ret;
> + struct drbg_gen genbuf;
> + genbuf.outbuf = outbuf;
> + genbuf.outlen = outlen;
> + genbuf.addtl_input = addtl_input;
> + genbuf.addtllen = addtllen;
> + genbuf.test_data = NULL;
> + ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
> + return ret;
> +}
> +
> +/*
> + * TEST code
> + *
> + * This is a wrapper to the kernel crypto API function of
> + * crypto_rng_get_bytes() to allow the caller to provide additional data and
> + * allow furnishing of test_data
> + *
> + * @drng DRBG handle -- see crypto_rng_get_bytes
> + * @outbuf output buffer -- see crypto_rng_get_bytes
> + * @outlen length of output buffer -- see crypto_rng_get_bytes
> + * @addtl_input additional information string input buffer
> + * @addtllen length of additional information string buffer
> + * @test_data filled test data
> + *
> + * return
> + * see crypto_rng_get_bytes
> + */
> +static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
> + unsigned char *outbuf, unsigned int outlen,
> + unsigned char *addtl_input, size_t addtllen,
> + struct drbg_test_data *test_data)
> +{
> + int ret;
> + struct drbg_gen genbuf;
> + genbuf.outbuf = outbuf;
> + genbuf.outlen = outlen;
> + genbuf.addtl_input = addtl_input;
> + genbuf.addtllen = addtllen;
> + genbuf.test_data = test_data;
> + ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
> + return ret;
> +}
> +
> +/*
> + * TEST code
> + *
> + * This is a wrapper to the kernel crypto API function of
> + * crypto_rng_reset() to allow the caller to provide test_data
> + *
> + * @drng DRBG handle -- see crypto_rng_reset
> + * @pers personalization string input buffer
> + * @perslen length of additional information string buffer
> + * @test_data filled test data
> + *
> + * return
> + * see crypto_rng_reset
> + */
> +static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
> + unsigned char *pers, unsigned int perslen,
> + struct drbg_test_data *test_data)
> +{
> + int ret;
> + struct drbg_gen genbuf;
> + genbuf.outbuf = NULL;
> + genbuf.outlen = 0;
> + genbuf.addtl_input = pers;
> + genbuf.addtllen = perslen;
> + genbuf.test_data = test_data;
> + ret = crypto_rng_reset(drng, (u8 *)&genbuf, 0);
> + return ret;
> +}
> +
> +
> +#define DRBG_STATELEN(a) ((a)->core->statelen)
> +#define DRBG_BLOCKLEN(a) ((a)->core->blocklen_bytes)
> +/* only needed for CTR mode -- implicit key len with seedlen - blocklen
> + * according to table 3 */
> +#define DRBG_KEYLEN(drbg) (DRBG_STATELEN(drbg) - DRBG_BLOCKLEN(drbg))
ditto (get rid of these macros, please)
> +
> +/*
> + * DRBG flags bitmasks
> + *
> + * 31 (B) 27 19 (A) 0
> + * +-+-+-+-+------+---+---+---------------+
> + * |~|~|u|p|~~~~~~| 3 | 2 | 1 |
> + * +-+-+-+-+------+- -+---+---------------+
> + * ctl flags| |drbg use selection flags
> + *
> + */
> +
> +/* internal state control flags (B) */
> +#define DRBG_UNSEEDED ((drbg_flag_t)1<<27)
> +#define DRBG_PREDICTION_RESIST ((drbg_flag_t)1<<28)
> +
> +/* CTR type modifiers (A.1)*/
> +#define DRBG_CTRAES128 ((drbg_flag_t)1<<0)
> +#define DRBG_CTRAES192 ((drbg_flag_t)1<<1)
> +#define DRBG_CTRAES256 ((drbg_flag_t)1<<2)
> +#define DRBG_CTRSERPENT128 ((drbg_flag_t)1<<3)
> +#define DRBG_CTRSERPENT192 ((drbg_flag_t)1<<4)
> +#define DRBG_CTRSERPENT256 ((drbg_flag_t)1<<5)
> +#define DRBG_CTRTWOFISH128 ((drbg_flag_t)1<<6)
> +#define DRBG_CTRTWOFISH192 ((drbg_flag_t)1<<7)
> +#define DRBG_CTRTWOFISH256 ((drbg_flag_t)1<<8)
> +#define DRBG_CTR_MASK (DRBG_CTRAES128 | DRBG_CTRAES192 | DRBG_CTRAES256| \
> + DRBG_CTRSERPENT128 | DRBG_CTRSERPENT192 | \
> + DRBG_CTRSERPENT256 | DRBG_CTRTWOFISH128 | \
> + DRBG_CTRTWOFISH192 | DRBG_CTRTWOFISH256)
> +
> +/* HASH type modifiers (A.2)*/
> +#define DRBG_HASHSHA1 ((drbg_flag_t)1<<9)
> +#define DRBG_HASHSHA224 ((drbg_flag_t)1<<10)
> +#define DRBG_HASHSHA256 ((drbg_flag_t)1<<11)
> +#define DRBG_HASHSHA384 ((drbg_flag_t)1<<12)
> +#define DRBG_HASHSHA512 ((drbg_flag_t)1<<13)
> +#define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 | \
> + DRBG_HASHSHA256 | DRBG_HASHSHA384 | \
> + DRBG_HASHSHA512)
> +
> +/* HMAC type modifiers (A.2)*/
> +#define DRBG_HMACSHA1 ((drbg_flag_t)1<<14)
> +#define DRBG_HMACSHA224 ((drbg_flag_t)1<<15)
> +#define DRBG_HMACSHA256 ((drbg_flag_t)1<<16)
> +#define DRBG_HMACSHA384 ((drbg_flag_t)1<<17)
> +#define DRBG_HMACSHA512 ((drbg_flag_t)1<<18)
> +#define DRBG_HMAC_MASK (DRBG_HMACSHA1 | DRBG_HMACSHA224 | \
> + DRBG_HMACSHA256 | DRBG_HMACSHA384 | \
> + DRBG_HMACSHA512)
> +
> +#define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK | DRBG_HMAC_MASK)
> +
Seems to me this flagging scheme could be improved to not waste bits
with redundant information. For instance: repeating the strenght for
each one DRBG, as well as repeating the crypt alg for each one HASH and
HMAC DRBG. Also, you could use to defive a fixed set of flags that
describe an unique drbg instance, so users can get it by using that static set,
instead of creating dynamic ones on their own (makes the implementation
stronger and fool-proof, IMO).
Regards,
-- Rafael
> +/* helper functions */
> +static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
> +{
> + /* max_bits is in bits, but buflen is in bytes */
> + return (1 << (drbg->core->max_bits - 3));
> +}
> +
> +static inline size_t drbg_max_addtl(struct drbg_state *drbg)
> +{
> + return (1UL<<(drbg->core->max_addtllen));
> +}
> +
> +static inline size_t drbg_max_requests(struct drbg_state *drbg)
> +{
> + return (1UL<<(drbg->core->max_req));
> +}
> +
> +#endif /* _DRBG_H */
> --
> 1.8.5.3
>
>
Signed-off-by: Stephan Mueller <[email protected]>
---
diff --git a/crypto/Makefile b/crypto/Makefile
index b29402a..0d63373 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_CRYPTO_842) += 842.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
+obj-$(CONFIG_CRYTPO_DRBG) += drbg.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
--
1.8.5.3
The header file includes the definition of:
* DRBG data structures with
- struct drbg_state as main structure
- struct drbg_core referencing the backend ciphers
- struct drbg_state_ops callbach handlers for specific code
supporting the Hash, HMAC, CTR DRBG implementations
- struct drbg_string defining a linked list for input data
- struct drbg_test_data holding the test "entropy" data for CAVS
testing and testmgr.c
- struct drbg_gen allowing test data, additional information
string and personalization string data to be funneled through
the kernel crypto API -- the DRBG requires additional
parameters when invoking the reset and random number
generation requests than intended by the kernel crypto API
* wrapper function to the kernel crypto API functions using struct
drbg_gen to pass through all data needed for DRBG
* wrapper functions to kernel crypto API functions usable for testing
code to inject test_data into the DRBG as needed by CAVS testing and
testmgr.c.
* DRBG flags required for the operation of the DRBG and for selecting
the particular DRBG type and backend cipher
* getter functions for data from struct drbg_core
Changes to v1:
* Changes due to modification of drbg.c as documented in PATCH 1
* Fix coding style and apply scripts/checkpatch.pl
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 include/crypto/drbg.h
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
new file mode 100644
index 0000000..f52e7ca
--- /dev/null
+++ b/include/crypto/drbg.h
@@ -0,0 +1,292 @@
+/*
+ * DRBG based on NIST SP800-90A
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _DRBG_H
+#define _DRBG_H
+
+
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <crypto/hash.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/slab.h> /* needed for kzalloc */
+#include <crypto/internal/rng.h>
+#include <crypto/rng.h>
+#include <linux/fips.h>
+#include <linux/spinlock.h>
+
+/*
+ * Concatenation Helper and string operation helper
+ *
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+
+struct drbg_string {
+ const unsigned char *buf;
+ size_t len;
+ struct drbg_string *next;
+};
+
+static inline void drbg_string_fill(struct drbg_string *string,
+ const unsigned char *buf, size_t len)
+{
+ string->buf = buf;
+ string->len = len;
+ string->next = NULL;
+}
+
+struct drbg_state;
+typedef uint32_t drbg_flag_t;
+
+struct drbg_core {
+ drbg_flag_t flags; /* flags for the cipher */
+ __u8 statelen; /* maximum state length */
+ __u8 max_addtllen; /* maximum length of personalization string or
+ additional input string -- exponent for base
+ 2 */
+ __u8 max_bits; /* maximum bits per RNG request -- exponent for
+ base 2*/
+ __u8 max_req; /* maximum number of requests -- exponent for
+ base 2 */
+ __u8 blocklen_bytes; /* block size of output in bytes */
+ char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
+ char cra_driver_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto
+ * API */
+ char backend_cra_name[CRYPTO_MAX_ALG_NAME]; /* kernel crypto API
+ * backend cipher name */
+};
+
+struct drbg_state_ops {
+ int (*update)(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed);
+ unsigned int (*generate)(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl);
+ int (*crypto_init)(struct drbg_state *drbg);
+ int (*crypto_fini)(struct drbg_state *drbg);
+
+};
+
+struct drbg_test_data {
+ struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */
+};
+
+struct drbg_state {
+ spinlock_t drbg_lock; /* lock around DRBG */
+ unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *C; /* hash: static value 10.1.1.1 1b)
+ * hmac / ctr: key */
+ size_t reseed_ctr; /* Number of RNG requests since last reseed --
+ * 10.1.1.1 1c) */
+ unsigned char *scratchpad; /* some memory the DRBG can use for its
+ * operation -- allocated during init */
+ void *priv_data; /* Data needed for specific cipher
+ * implementation */
+ bool seeded; /* DRBG fully seeded? */
+ bool pr; /* Prediction resistance enabled? */
+#ifdef CONFIG_CRYPTO_FIPS
+ bool fips_primed; /* Continuous test primed? */
+ unsigned char *prev; /* previous output value of DRBG_BLOCKLEN for
+ * FIPS 140-2 continuous test */
+#endif
+ const struct drbg_state_ops *d_ops;
+ const struct drbg_core *core;
+ struct drbg_test_data *test_data;
+};
+
+/* helper functions */
+static inline __u8 drbg_statelen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->statelen;
+ return 0;
+}
+
+static inline __u8 drbg_blocklen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->blocklen_bytes;
+ return 0;
+}
+
+static inline __u8 drbg_keylen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return (drbg->core->statelen - drbg->core->blocklen_bytes);
+ return 0;
+}
+
+static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
+{
+ /* max_bits is in bits, but buflen is in bytes */
+ return (1 << (drbg->core->max_bits - 3));
+}
+
+static inline size_t drbg_max_addtl(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_addtllen));
+}
+
+static inline size_t drbg_max_requests(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_req));
+}
+
+/* kernel crypto API input data structure for DRBG generate in case dlen
+ * is set to 0 */
+struct drbg_gen {
+ unsigned char *outbuf; /* output buffer for random numbers */
+ unsigned int outlen; /* size of output buffer */
+ struct drbg_string *addtl; /* input buffer for
+ * additional information string */
+ struct drbg_test_data *test_data; /* test data */
+};
+
+/*
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ struct drbg_string *addtl)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl = addtl;
+ genbuf.test_data = NULL;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data and
+ * allow furnishing of test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ struct drbg_string *addtl,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl = addtl;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_reset() to allow the caller to provide test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_reset
+ * @pers personalization string input buffer
+ * @perslen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_reset
+ */
+static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
+ struct drbg_string *pers,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = NULL;
+ genbuf.outlen = 0;
+ genbuf.addtl = pers;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_reset(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/* DRBG type flags */
+#define DRBG_CTR ((drbg_flag_t)1<<0)
+#define DRBG_HMAC ((drbg_flag_t)1<<1)
+#define DRBG_HASH ((drbg_flag_t)1<<2)
+#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
+/* DRBG strength flags */
+#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
+#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
+#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
+#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
+ DRBG_STRENGTH256)
+
+enum drbg_prefixes {
+ DRBG_PREFIX0 = 0x00,
+ DRBG_PREFIX1,
+ DRBG_PREFIX2,
+ DRBG_PREFIX3
+};
+
+#endif /* _DRBG_H */
The different DRBG types of CTR, Hash, HMAC can be enabled or disabled
at compile time. At least one DRBG type shall be selected.
The default is the HMAC DRBG as its code base is smallest.
Signed-off-by: Stephan Mueller <[email protected]>
---
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7bcb70d..2cdf9c6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -23,7 +23,7 @@ comment "Crypto core or helper"
config CRYPTO_FIPS
bool "FIPS 200 compliance"
- depends on CRYPTO_ANSI_CPRNG && !CRYPTO_MANAGER_DISABLE_TESTS
+ depends on (CRYPTO_ANSI_CPRNG || CRYTPO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
help
This options enables the fips boot option which is
required if you want to system to operate in a FIPS 200
@@ -1380,6 +1380,40 @@ config CRYPTO_ANSI_CPRNG
ANSI X9.31 A.2.4. Note that this option must be enabled if
CRYPTO_FIPS is selected
+menuconfig CRYTPO_DRBG
+ tristate "NIST SP800-90A DRBG"
+ depends on CRYPTO
+ select CRYPTO_RNG
+ help
+ NIST SP800-90A compliant DRBG. In the following submenu, one or
+ more of the DRBG types must be selected.
+
+if CRYTPO_DRBG
+
+config CRYPTO_DRBG_HMAC
+ bool "Enable HMAC DRBG"
+ default y
+ depends on CRYTPO_DRBG
+ select CRYPTO_HMAC
+ help
+ Enable the HMAC DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_HASH
+ bool "Enable Hash DRBG"
+ depends on CRYTPO_DRBG
+ select CRYPTO_HASH
+ help
+ Enable the Hash DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_CTR
+ bool "Enable CTR DRBG"
+ depends on CRYTPO_DRBG
+ select CRYPTO_AES
+ help
+ Enable the CTR DRBG variant as defined in NIST SP800-90A.
+
+endif #CRYTPO_DRBG
+
config CRYPTO_USER_API
tristate
--
1.8.5.3
All types of the DRBG (CTR, HMAC, Hash) are covered with test vectors.
In addition, all permutations of use cases of the DRBG are covered:
* with and without predition resistance
* with and without additional information string
* with and without personalization string
As the DRBG implementation is agnositc of the specific backend cipher,
only test vectors for one specific backend cipher is used. For example:
the Hash DRBG uses the same code paths irrespectively of using SHA-256
or SHA-512. Thus, the test vectors for SHA-256 cover the testing of all
DRBG code paths of SHA-512.
Changes to v1:
* Fix coding style and apply scripts/checkpatch.pl
Signed-off-by: Stephan Mueller <[email protected]>
---
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 7d44aa3..1f48312 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -92,6 +92,29 @@ struct cprng_testvec {
unsigned short loops;
};
+struct drbg_testvec {
+ unsigned char *entropy; /* entropy string for initialization -- this
+ * string is a concatenation of the entropy
+ * and nonce variable from CAVS */
+ size_t entropylen; /* length of entropy and nonce variable */
+ unsigned char *entpra; /* for prediction resistance: entropy for
+ * first reseeding */
+ unsigned char *entprb; /* for prediction resistance: entropy for
+ * second reseeding */
+ size_t entprlen; /* length of prediction resistance entropy */
+ unsigned char *addtla; /* additional input string for first random
+ * value */
+ unsigned char *addtlb; /* additional input string for second random
+ * value */
+ size_t addtllen; /* length of additional input string */
+ unsigned char *pers; /* personalization string */
+ size_t perslen; /* personalization string length */
+ unsigned char *expected; /* expected random value -- for CAVS test,
+ this value does not apply and the memcmp
+ in drbg_cavs_test does not apply either*/
+ size_t expectedlen; /* length of expected random value */
+};
+
static char zeroed_string[48];
/*
@@ -19162,6 +19185,834 @@ static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
},
};
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG with prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_pr_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86"
+ "\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf"
+ "\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6"
+ "\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62"
+ "\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f"
+ "\x67\xb0\x67\x7a\x5e\x9e\x0c\x62",
+ .entprb = (unsigned char *)
+ "\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf"
+ "\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0"
+ "\x8c\xee\xeb\x9c\xf5\x31\x98\x31",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7"
+ "\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49"
+ "\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d"
+ "\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe"
+ "\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1"
+ "\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5"
+ "\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf"
+ "\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6"
+ "\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5"
+ "\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce"
+ "\x30\x81\xa6\x8f\x27\x14\xf8\x1c",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
+ "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
+ "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
+ "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
+ "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
+ "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
+ .entprb = (unsigned char *)
+ "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
+ "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
+ "\x76\xaa\x55\x04\x8b\x0a\x72\x95",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
+ "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
+ "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
+ "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
+ "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
+ "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
+ "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
+ "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
+ "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
+ "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
+ "\x50\x47\xa3\x63\x81\x16\xaf\x19",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
+ "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
+ "\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
+ .addtlb = (unsigned char *)
+ "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
+ "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
+ "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85"
+ "\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72"
+ "\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8"
+ "\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9"
+ "\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60"
+ "\xba\x0a\xde\x57\x5b\x4b\x9f\x29",
+ .entprb = (unsigned char *)
+ "\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd"
+ "\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4"
+ "\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25"
+ "\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde"
+ "\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5"
+ "\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9"
+ "\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c"
+ "\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e"
+ "\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c"
+ "\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae"
+ "\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c"
+ "\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe"
+ "\x90\x35\x0d\x4c\x4d\x85\xe7\x13",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7"
+ "\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90"
+ "\xa4\x1b\xe1\xe2\x53\xcc\x61\x47",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6"
+ "\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4"
+ "\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87"
+ "\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c"
+ "\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12"
+ "\x19\xaf\x97\x2d\x5f\xf9\xff\xfc",
+ .entprb = (unsigned char *)
+ "\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73"
+ "\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6"
+ "\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31"
+ "\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65"
+ "\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18"
+ "\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42"
+ "\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50"
+ "\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b"
+ "\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f"
+ "\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0"
+ "\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda"
+ "\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44"
+ "\x63\x4a\x68\x72\xe9\xf5\x55\xfe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c"
+ "\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff"
+ "\x4a\x85\xca\x80\xfe\x0d\x1c\xd0",
+ .addtlb = (unsigned char *)
+ "\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2"
+ "\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89"
+ "\x42\x58\x9e\xd6\xcc\xad\x7b\x1e",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1"
+ "\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52"
+ "\x82\x4c\xdc\x19\xb8\xf8\x92\x5c",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a"
+ "\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96"
+ "\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46"
+ "\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92"
+ "\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46"
+ "\xe2\x9a\x29\x51\x81\x56\x9f\x54",
+ .entprb = (unsigned char *)
+ "\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc"
+ "\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65"
+ "\x8a\x2a\x77\xa8\x69\x90\x89\xf4",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2"
+ "\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1"
+ "\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4"
+ "\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf"
+ "\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc"
+ "\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8"
+ "\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b"
+ "\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e"
+ "\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22"
+ "\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc"
+ "\xb1\xcd\x09\xd6\x92\xd0\x28\x3f",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f"
+ "\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f"
+ "\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05"
+ "\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4"
+ "\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26"
+ "\x46\xd9\x26\xa2\x19\xd4\x94\x43",
+ .entprb = (unsigned char *)
+ "\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79"
+ "\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98"
+ "\x51\x78\x72\xb2\x79\xfd\x2c\xff",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7"
+ "\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda"
+ "\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa"
+ "\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40"
+ "\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda"
+ "\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37"
+ "\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70"
+ "\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b"
+ "\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5"
+ "\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd"
+ "\xcd\x66\xb5\x01\x69\x66\xa0\x3c",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3"
+ "\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56"
+ "\x6d\x99\x3b\xc6\x58\xda\x03\xf6",
+ .addtlb = (unsigned char *)
+ "\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c"
+ "\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44"
+ "\xc6\x03\xa2\xfb\x13\x20\x19\xb7",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
+ "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
+ "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
+ "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
+ "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
+ "\x20\x28\xad\xf2\x60\xd7\xcd\x45",
+ .entprb = (unsigned char *)
+ "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
+ "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
+ "\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
+ "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
+ "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
+ "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
+ "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
+ "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
+ "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
+ "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
+ "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
+ "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
+ "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
+ "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
+ "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd"
+ "\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01"
+ "\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15"
+ "\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a"
+ "\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96"
+ "\xbb\x81\x6a\xcc\xb5\xae\x55\xb6",
+ .entprb = (unsigned char *)
+ "\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2"
+ "\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e"
+ "\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14"
+ "\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6"
+ "\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7"
+ "\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77"
+ "\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5"
+ "\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6"
+ "\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1"
+ "\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40"
+ "\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8"
+ "\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72"
+ "\xda\x3f\xad\x2b\xba\x00\x6b\xd1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03"
+ "\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6"
+ "\x86\x88\x55\x28\xc1\x69\xdd\x76",
+ .addtlb = (unsigned char *)
+ "\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7"
+ "\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa"
+ "\x00\x99\x2a\xdd\x0a\x00\x50\x82",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8"
+ "\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda"
+ "\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42"
+ "\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15"
+ "\xb4\xec\x80\xb1",
+ .entprb = (unsigned char *)
+ "\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9"
+ "\x28\x07\xeb\xc2",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe"
+ "\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc"
+ "\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18"
+ "\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce"
+ "\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b"
+ "\x8a\xf1\x23\xa8",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77"
+ "\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73"
+ "\x67\xd1\x08\xf8",
+ .entprb = (unsigned char *)
+ "\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc"
+ "\xd4\xba\x04\x58",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d"
+ "\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc"
+ "\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7"
+ "\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc"
+ "\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c"
+ "\xc1\x02\x41\x82",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8"
+ "\xeb\xb3\x01\x76",
+ .addtlb = (unsigned char *)
+ "\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25"
+ "\xd0\x7f\xcc\x43",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b"
+ "\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66"
+ "\xc3\x0f\xe3\xb0",
+ .entprb = (unsigned char *)
+ "\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8"
+ "\xd6\x9c\x9d\xe8",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b"
+ "\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10"
+ "\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69"
+ "\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc"
+ "\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f"
+ "\x72\x82\x0c\xcf",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed"
+ "\x21\x52\xb3\xad",
+ .perslen = 16,
+ }, {
+ .entropy = (unsigned char *)
+ "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
+ "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
+ "\xc4\x2c\xe8\x10",
+ .entprb = (unsigned char *)
+ "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
+ "\x08\xf7\xa5\x01",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
+ "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
+ "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
+ "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
+ "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
+ "\x23\xc5\x1f\x68",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
+ "\x23\x6d\xad\x1d",
+ .addtlb = (unsigned char *)
+ "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
+ "\xbc\x59\x31\x8c",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
+ "\x37\x3c\x5c\x0b",
+ .perslen = 16,
+ },
+};
+
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG without prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3"
+ "\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19"
+ "\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31"
+ "\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64"
+ "\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5"
+ "\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3"
+ "\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11"
+ "\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81"
+ "\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63"
+ "\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7"
+ "\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c"
+ "\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91"
+ "\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d"
+ "\xd4\x31\xf4\xc9\xf7\x04\x27\xdf",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
+ "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
+ "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
+ "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
+ "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
+ "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
+ "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
+ "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
+ "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
+ "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
+ "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
+ "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
+ "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
+ "\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
+ "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
+ "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
+ .addtlb = (unsigned char *)
+ "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
+ "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
+ "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb"
+ "\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4"
+ "\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1"
+ "\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28"
+ "\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b"
+ "\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46"
+ "\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6"
+ "\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72"
+ "\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1"
+ "\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77"
+ "\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9"
+ "\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e"
+ "\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16"
+ "\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1"
+ "\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda"
+ "\x57\x6b\xce\xa4\x1c\x66\x3d\xbc",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a"
+ "\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74"
+ "\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc"
+ "\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb"
+ "\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13"
+ "\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6"
+ "\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36"
+ "\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64"
+ "\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea"
+ "\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95"
+ "\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e"
+ "\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd"
+ "\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06"
+ "\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2"
+ "\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e"
+ "\x77\xc5\x3d\x9e\x03\xe3\xa5\x78",
+ .addtlb = (unsigned char *)
+ "\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a"
+ "\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b"
+ "\x74\x7f\xa6\xf6\x80\xcd\x9b\x21",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20"
+ "\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73"
+ "\xa9\x65\xb1\x10\xc1\xdc\x77\x7c",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
+ "\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
+ "\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c"
+ "\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75"
+ "\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6"
+ "\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97"
+ "\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60"
+ "\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf"
+ "\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99"
+ "\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19"
+ "\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68"
+ "\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0"
+ "\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd"
+ "\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94"
+ "\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15"
+ "\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4"
+ "\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5"
+ "\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf"
+ "\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d"
+ "\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6"
+ "\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16"
+ "\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62"
+ "\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d"
+ "\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4"
+ "\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec"
+ "\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f"
+ "\x50\x9a\x8c\x85\x90\x87\x03\x9c",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d"
+ "\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf"
+ "\x2f\xf3\x00\x34\xd8\x26\x8e\x3b",
+ .addtlb = (unsigned char *)
+ "\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9"
+ "\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14"
+ "\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
+ "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
+ "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
+ "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
+ "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
+ "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
+ "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
+ "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
+ "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
+ "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
+ "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
+ "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
+ "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
+ "\x10\x37\x41\x03\x0c\xcc\x3a\x56",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
+ "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
+ "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78"
+ "\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11"
+ "\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb"
+ "\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0"
+ "\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37"
+ "\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae"
+ "\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0"
+ "\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad"
+ "\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82"
+ "\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7"
+ "\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4"
+ "\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49"
+ "\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30"
+ "\x35\x24\xcc\x9c\xc5\xea\x54\xa1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96"
+ "\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62"
+ "\xd3\x13\x3b\x83\xe4\x9c\x82\x0b",
+ .addtlb = (unsigned char *)
+ "\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2"
+ "\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25"
+ "\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8"
+ "\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15"
+ "\x36\x60\x3b\xca\x37\xc9\xee\x29",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9"
+ "\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40"
+ "\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9"
+ "\xac\x9b\xbb\x00",
+ .entropylen = 40,
+ .expected = (unsigned char *)
+ "\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17"
+ "\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33"
+ "\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48"
+ "\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79"
+ "\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf"
+ "\x9a\x9d\xf1\x0d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f"
+ "\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec"
+ "\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0"
+ "\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6"
+ "\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3"
+ "\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf"
+ "\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16"
+ "\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f"
+ "\xb4\xf0\x7e\x1d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8"
+ "\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1"
+ "\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a"
+ "\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3"
+ "\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e"
+ "\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8"
+ "\xcb\x2d\xd6\xb0",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74"
+ "\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34"
+ "\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21"
+ "\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e"
+ "\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1"
+ "\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc"
+ "\xc3\xdf\xb3\x81",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6"
+ "\x91\x4d\x81\x56",
+ .addtlb = (unsigned char *)
+ "\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb"
+ "\x4a\x55\xd1\xc6",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9"
+ "\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e"
+ "\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75"
+ "\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee"
+ "\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb"
+ "\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45"
+ "\x34\x30\x0c\x3d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a"
+ "\x0b\xc6\x97\x54",
+ .perslen = 16,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
+ "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
+ "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
+ "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
+ "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
+ "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
+ "\x2b\x49\x1e\x5c",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
+ "\x44\x85\xe7\xfe",
+ .addtlb = (unsigned char *)
+ "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
+ "\x82\x16\x62\x7f",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
+ "\x8e\xcf\xe0\x02",
+ .perslen = 16,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 4
#define CAST5_DEC_TEST_VECTORS 4
The DRBG test code implements the CAVS test approach.
As discussed for the test vectors, all DRBG types are covered with
testing. However, not every backend cipher is covered with testing. To
prevent the testmgr from logging missing testing, the NULL test is
registered for all backend ciphers not covered with specific test cases.
All currently implemented DRBG types and backend ciphers are definined
in SP800-90A. Therefore, the fips_allowed flag is set for all.
Changes to v1:
* Changes due to modification of drbg.c as documented in PATCH 1
* Fix coding style and apply scripts/checkpatch.pl
Signed-off-by: Stephan Mueller <[email protected]>
---
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 7795550..baa6cb7 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/rng.h>
+#include <crypto/drbg.h>
#include "internal.h"
@@ -108,6 +109,11 @@ struct cprng_test_suite {
unsigned int count;
};
+struct drbg_test_suite {
+ struct drbg_testvec *vecs;
+ unsigned int count;
+};
+
struct alg_test_desc {
const char *alg;
int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -121,6 +127,7 @@ struct alg_test_desc {
struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
struct cprng_test_suite cprng;
+ struct drbg_test_suite drbg;
} suite;
};
@@ -1712,6 +1719,101 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
return err;
}
+
+static int drbg_cavs_test(struct drbg_testvec *test, int pr,
+ const char *driver, u32 type, u32 mask)
+{
+ int ret = -EAGAIN;
+ struct crypto_rng *drng;
+ struct drbg_test_data test_data;
+ struct drbg_string addtl, pers, testentropy;
+ unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ drng = crypto_alloc_rng(driver, type, mask);
+ if (IS_ERR(drng)) {
+ printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for"
+ "%s\n", driver);
+ kzfree(buf);
+ return -ENOMEM;
+ }
+
+ test_data.testentropy = &testentropy;
+ drbg_string_fill(&testentropy, test->entropy, test->entropylen);
+ drbg_string_fill(&pers, test->pers, test->perslen);
+ ret = crypto_drbg_reset_test(drng, &pers, &test_data);
+ if (ret) {
+ printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
+ goto outbuf;
+ }
+
+ drbg_string_fill(&addtl, test->addtla, test->addtllen);
+ if (pr) {
+ drbg_string_fill(&testentropy, test->entpra, test->entprlen);
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen, &addtl, &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen, &addtl);
+ }
+ if (ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data for"
+ "driver %s\n", driver);
+ goto outbuf;
+ }
+
+ drbg_string_fill(&addtl, test->addtlb, test->addtllen);
+ if (pr) {
+ drbg_string_fill(&testentropy, test->entprb, test->entprlen);
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen, &addtl, &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen, &addtl);
+ }
+ if (ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data for"
+ "driver %s\n", driver);
+ goto outbuf;
+ }
+
+ ret = memcmp(test->expected, buf, test->expectedlen);
+
+outbuf:
+ crypto_free_rng(drng);
+ kzfree(buf);
+ return ret;
+}
+
+
+static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ int err = 0;
+ int pr = 0;
+ int i = 0;
+ struct drbg_testvec *template = desc->suite.drbg.vecs;
+ unsigned int tcount = desc->suite.drbg.count;
+
+ if ((0 == memcmp(driver, "drbg(pr(", 8)) ||
+ (0 == memcmp(driver, "drbg_pr_", 8)))
+ pr = 1;
+
+ for (i = 0; i < tcount; i++) {
+ err = drbg_cavs_test(&template[i], pr, driver, type, mask);
+ if (err) {
+ printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
+ i, driver);
+ err = -EINVAL;
+ break;
+ }
+ }
+ return err;
+
+}
+
static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
{
@@ -2273,6 +2375,171 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "digest_null",
.test = alg_test_null,
}, {
+ .alg = "drbg(nopr(ctr(aes128)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg(nopr(ctr(aes192)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes192_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes192_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg(nopr(ctr(aes256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha1)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(nopr(hmac(sha256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_hmac_sha256_tv_template,
+ .count =
+ ARRAY_SIZE(drbg_nopr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha384)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(hmac(sha256))) test */
+ .alg = "drbg(nopr(hmac(sha512)))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha1))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(nopr(sha256))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha384))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(nopr(sha256)) test */
+ .alg = "drbg(nopr(sha512))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(ctr(aes128)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(aes128)) test */
+ .alg = "drbg(pr(ctr(aes192)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(aes128)) test */
+ .alg = "drbg(pr(ctr(aes256)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha1)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(hmac(sha256)))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha384)))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(hmac(sha256))) test */
+ .alg = "drbg(pr(hmac(sha512)))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha1))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg(pr(sha256))",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha384))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ /* There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg(pr(sha256)) test */
+ .alg = "drbg(pr(sha512))",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
.alg = "ecb(__aes-aesni)",
.test = alg_test_null,
.fips_allowed = 1,
This is a clean-room implementation of the DRBG defined in SP800-90A.
All three viable DRBGs defined in the standard are implemented:
* HMAC: This is the leanest DRBG and compiled per default
* Hash: The more complex DRBG can be enabled at compile time
* CTR: The most complex DRBG can also be enabled at compile time
The DRBG implementation offers the following:
* All three DRBG types are implemented with a derivation function.
* All DRBG types are available with and without prediction resistance.
* All SHA types of SHA-1, SHA-256, SHA-384, SHA-512 are available for
* the HMAC and Hash DRBGs.
* All AES types of AES-128, AES-192 and AES-256 are available for the
* CTR DRBG.
* A self test is implemented with drbg_healthcheck().
* The FIPS 140-2 continuous self test is implemented.
* Additional cipher primitives, such as Serpent or Twofish, can be
* added to the DRBG without changing the implementation. The only
* change necessary is to the DRBG definition given in the cores[]
* array.
Changes to v1:
* Overhauling code structure for simpler code as suggested by Rafael Aquini:
- each DRBG type exports only two crypto functions,
- the individual DRBG implementations structure closely according to
SP 800-90A,
- using struct drbg_string to refer to buffers to avoid too many
function parameters and prevent multiple data structure conversions
- use inline more thoroughly
- replace macros with small inline functions
- remove unnecessary indirections
- replace of large stack variables with a scratch buffer allocated at
the beginning of DRBG operation -- see comments about scratchpad
throughout the code
* Revamping DRBG flags usage: flags are only intended to select the appropriate
DRBG type and DRBG strength. Flags are not intended to be visible to
external callers.
* Adding comments throughout the code to refer to the appropriate steps
documented in SP 800-90A.
* Fix invocation of kernel crypto API hash
* Fix coding style and apply scripts/checkpatch.pl
* Change locking approach: only very small code sections are guarded by a lock.
This implies that the entire DRBG operates on a shadow copy of the original
DRBG state -- see comments for drbg_copy_drbg
* Perform thorough testing:
- Performing of a full scale CAVS test with CAVS interface available at
http://www.chronox.de/drbg.html
- Performing tests by obtaining data which is not a multiple of cipher block
size and check it with the ent tool to ensure that the generation loop
does not reuse stale buffers to avoid errors like CVE-2013-4345.
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..808852b
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1790 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers
+ * char personalization = "some-string";
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, "some-string", strlen(addtl)); *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+const struct drbg_core cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 0 on error
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* invert the memcmp result, because the test shall pass when the
+ * two compared values do not match */
+ if (ret)
+ return true;
+ else
+ return false;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val, size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *out, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = out + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ size_t padlen = 1; /* already reserve space for 0x80 */
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ while (0 != ((8 + inputlen + padlen) % (drbg_blocklen(drbg))))
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, 8);
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(out + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static unsigned int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ if (drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static unsigned int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ if (drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data))
+ return 0;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static unsigned int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ unsigned int len = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ memcpy(drbg->scratchpad, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ if (drbg_kcapi_hash(drbg, NULL, dst, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static unsigned int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ if (drbg_hash_process_addtl(drbg, addtl))
+ return 0;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ if (drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1)) {
+ len = 0;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+ struct drbg_string *data2;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg)))
+ return -EINVAL;
+
+ if (drbg->test_data) {
+ data1.buf = drbg->test_data->testentropy->buf;
+ data1.len = drbg->test_data->testentropy->len;
+ data1.next = NULL;
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = (drbg_sec_strength(drbg->core->flags) / 8);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input) */
+ if (pers && 0 < pers->len) {
+ data2 = pers;
+ data2->next = NULL;
+ data1.next = data2;
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops are set outside, as the struct is const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside, as the struct is const */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C)
+ return -EINVAL;
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ /* read-only data */
+ tmp->core = drbg->core;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ tmp->d_ops = drbg->d_ops;
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static unsigned int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf)
+ return 0;
+ if (addtl && NULL == addtl->buf && 0 < addtl->len)
+ return 0;
+
+ if (drbg_make_shadow(drbg, &shadow))
+ return 0;
+ /* 9.3.1 step 2 */
+ if (buflen > (drbg_max_request_bytes(shadow)))
+ goto err;
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow)))
+ goto err;
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init && shadow->d_ops->crypto_init(shadow))
+ goto err;
+
+ if (shadow->pr || !shadow->seeded) {
+ /* 9.3.1 steps 7.1 through 7.3 */
+ if (drbg_seed(shadow, addtl, true))
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = drbg->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @flags Flags defining the requested DRBG type and cipher type. The flags
+ * are defined in drbg.h and may be XORed. Beware, if you XOR multiple
+ * cipher types together, the code picks the core on a first come first
+ * serve basis as it iterates through the available cipher cores and
+ * uses the one with the first match. The minimum required flags are:
+ * cipher type flag
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ drbg->core = &cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ printk(KERN_INFO "drbg: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ printk(KERN_INFO "drbg: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if (0 == memcmp(cra_name + start, cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static inline void drbg_fill_array(unsigned long i, unsigned long j, int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))", 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+
+ if (ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ printk(KERN_INFO "drbg: Not all available DRBGs registered"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for (j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
Am Montag, 17. M?rz 2014, 08:34:06 schrieb Stephan Mueller:
> +static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
> + bool reseed)
> +{
> + int ret = 0;
> + unsigned char *entropy = NULL;
> + size_t entropylen = 0;
> + struct drbg_string data1;
> + struct drbg_string *data2;
> +
> + /* 9.1 / 9.2 / 9.3.1 step 3 */
> + if (pers && pers->len > (drbg_max_addtl(drbg)))
> + return -EINVAL;
> +
> + if (drbg->test_data) {
> + data1.buf = drbg->test_data->testentropy->buf;
> + data1.len = drbg->test_data->testentropy->len;
> + data1.next = NULL;
> + } else {
> + /* Gather entropy equal to the security strength of the DRBG.
> + * With a derivation function, a nonce is required in addition
> + * to the entropy. A nonce must be at least 1/2 of the
security
> + * strength of the DRBG in size. Thus, entropy * nonce is 3/2
> + * of the strength. The consideration of a nonce is only
> + * applicable during initial seeding. */
> + entropylen = (drbg_sec_strength(drbg->core->flags) / 8);
drbg_sec_strength returns the strength in bytes, thus the division by 8 must
be removed
> + if (!entropylen)
> + return -EFAULT;
> + if (!reseed)
> + /* make sure we round up strength/2 in
> + * case it is not divisible by 2 */
> + entropylen = ((entropylen + 1) / 2) * 3;
> +
> + entropy = kzalloc(entropylen, GFP_KERNEL);
> + if (!entropy)
> + return -ENOMEM;
> + get_random_bytes(entropy, entropylen);
> + drbg_string_fill(&data1, entropy, entropylen);
> + }
> +
> + /* concatenation of entropy with personalization str / addtl input) */
> + if (pers && 0 < pers->len) {
> + data2 = pers;
> + data2->next = NULL;
> + data1.next = data2;
> + }
> +
> + ret = drbg->d_ops->update(drbg, &data1, reseed);
> + if (ret)
> + goto out;
> +
> + drbg->seeded = true;
> + /* 10.1.1.2 / 10.1.1.3 step 5 */
> + drbg->reseed_ctr = 1;
> +
> +out:
> + if (entropy)
> + kzfree(entropy);
> + return ret;
> +}
> +
[...]
> +static unsigned int drbg_generate(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + unsigned int len = 0;
> + struct drbg_state *shadow = NULL;
> +
> + if (0 == buflen || !buf)
> + return 0;
> + if (addtl && NULL == addtl->buf && 0 < addtl->len)
> + return 0;
> +
> + if (drbg_make_shadow(drbg, &shadow))
> + return 0;
> + /* 9.3.1 step 2 */
> + if (buflen > (drbg_max_request_bytes(shadow)))
> + goto err;
> + /* 9.3.1 step 3 is implicit with the chosen DRBG */
> + /* 9.3.1 step 4 */
> + if (addtl && addtl->len > (drbg_max_addtl(shadow)))
> + goto err;
> + /* 9.3.1 step 5 is implicit with the chosen DRBG */
> + /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
> + * bit convoluted here, we make it simpler */
> + if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
> + shadow->seeded = false;
> +
> + /* allocate cipher handle */
> + if (shadow->d_ops->crypto_init && shadow->d_ops->crypto_init(shadow))
> + goto err;
> +
> + if (shadow->pr || !shadow->seeded) {
> + /* 9.3.1 steps 7.1 through 7.3 */
> + if (drbg_seed(shadow, addtl, true))
> + goto err;
> + /* 9.3.1 step 7.4 */
> + addtl = NULL;
> + }
> + /* 9.3.1 step 8 and 10 */
> + len = drbg->d_ops->generate(shadow, buf, buflen, addtl);
This needs to be shadow->d_ops
> +
> + /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
> + shadow->reseed_ctr++;
> +
> +err:
> + if (shadow->d_ops->crypto_fini)
> + shadow->d_ops->crypto_fini(shadow);
> + drbg_restore_shadow(drbg, &shadow);
> + return len;
> +}
Ciao
Stephan
Stephan Mueller wrote:
> This is a clean-room implementation of the DRBG defined in SP800-90A.
Why? I guess it's for certification?
> +static bool drbg_fips_continuous_test(struct drbg_state *drbg,
> + unsigned char *buf)
> ...
> + ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
> + ...
> + /* invert the memcmp result, because the test shall pass when the
> + * two compared values do not match */
> + if (ret)
> + return true;
> + else
> + return false;
This looks strange. The return value of memcmp() is not really
a boolean, and the code appears not to match the comment because the
numeric value of ret is not actually inverted. How about this:
ret = memcmp(...);
...
/* the test shall pass when the compared values are not equal */
return ret != 0;
Regards,
Clemens
Am Donnerstag, 20. M?rz 2014, 09:12:55 schrieb Clemens Ladisch:
Hi Clemens,
> Stephan Mueller wrote:
> > This is a clean-room implementation of the DRBG defined in SP800-90A.
>
> Why? I guess it's for certification?
As per SP800-131A, the ANSI X9.31 DRNG is sunset by the end of 2014 and not
allowed to be used in FIPS 140-2 compliant environments. The kernel crypto API
implements an ANSI X9.31 DRNG in crypto/ansi_cprng.c as the only DRNG that
complies with FIPS 140-2 at this time.
Without a replacement for this ANSI X9.31 DRNG, the kernel will not have an
FIPS 140-2 approved DRNG any more starting from 2015.
>
> > +static bool drbg_fips_continuous_test(struct drbg_state *drbg,
> > + unsigned char *buf)
> > ...
> > + ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
> > + ...
> > + /* invert the memcmp result, because the test shall pass when the
> > + * two compared values do not match */
> > + if (ret)
> > + return true;
> > + else
> > + return false;
>
> This looks strange. The return value of memcmp() is not really
> a boolean, and the code appears not to match the comment because the
> numeric value of ret is not actually inverted. How about this:
Correct, the comment does not match the code as I had invered the logic of
drbg_fips_continuous_test as per Rafael's comment. Yet, I did not update the
comment.
>
> ret = memcmp(...);
> ...
> /* the test shall pass when the compared values are not equal */
> return ret != 0;
I will add that change.
>
>
> Regards,
> Clemens
Thanks
Stephan
--
| Cui bono? |
Changes v3:
* fix invocation of drbg_sec_strength to determine the amount of seed needed
for the DRBG. The function returns information as a byte value, but the
invoker assumed a bit value.
* change default value returned by drbg_sec_strength to be the maximum entropy
defined by SP800-90A to catch erroneous invocations of the function.
* Fix invocaction of d_ops in drbg_generate: drbg->d_ops ==> shadow->d_ops
* Make return of drbg_fips_continuous_test cleaner as suggested by
Clemens Ladisch
* Fix comments on how to invoke the DRBG at the beginning of the file
* drbg_ctr_df: replace the for loop for calculation of padlen that used to
call up to 16 modulo operations with one modulo operation
* drbg_ctr_df: replace plain integer values with sizeof() to make code clearer
* drbg_hash_hashgen: replace memset() on drbg->scratchpad with memset()
on src/dst pointers to make code clearer
* as recommended by Peter Waltenberg: add re-invocation of self tests as
required by 11.3.3 -- the tests are commented out because they make no
mathematical sense. However, if a FIPS 140-2 validation requires these
tests, the code just needs to be activated.
* as recommended by Peter Waltenberg: add error path tests as required by
11.3.2 -- see new function of drbg_healthcheck_sanity
* add debug printk
* perform testing in FIPS 140-2 mode
* as recommended by Peter Waltenberg: add drbg_generate_long to generate
arbitrary long strings
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..6c866ef
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1975 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+const struct drbg_core cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static unsigned int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ if (drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static unsigned int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ if (drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data))
+ return 0;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static unsigned int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ unsigned int len = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ if (drbg_kcapi_hash(drbg, NULL, dst, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static unsigned int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ if (drbg_hash_process_addtl(drbg, addtl))
+ return 0;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ if (drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1)) {
+ len = 0;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+ struct drbg_string *data2;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %lu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input) */
+ if (pers && 0 < pers->len) {
+ data2 = pers;
+ data2->next = NULL;
+ data1.next = data2;
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops are set outside, as the struct is const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside, as the struct is const */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ /* read-only data */
+ tmp->core = drbg->core;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ tmp->d_ops = drbg->d_ops;
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static unsigned int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no buffer provided\n");
+ return 0;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return 0;
+ }
+
+ if (drbg_make_shadow(drbg, &shadow)) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return 0;
+ }
+ /* 9.3.1 step 2 */
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init && shadow->d_ops->crypto_init(shadow))
+ goto err;
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ if (drbg_seed(shadow, addtl, true))
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg(pr(hmac(sha256)))",
+ "drbg(pr(hmac(sha256)))", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg(pr(ctr(aes128)))",
+ "drbg(pr(ctr(aes128)))", 0, 0);
+ else
+ err = alg_test("drbg(pr(sha256))",
+ "drbg(pr(sha256))", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /* uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static unsigned int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ unsigned int slice = 0;
+ do {
+ unsigned int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (!tmplen)
+ return 0;
+ len += tmplen;
+ } while (slice > 0);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("drbg: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("drbg: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if (0 == memcmp(cra_name + start, cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
+#elif CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret)
+ goto outbuf;
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ if (len)
+ goto outdrbg;
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ if (len)
+ goto outdrbg;
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ if (0 == ret)
+ goto outdrbg;
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ if (!len)
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+outdrbg:
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
+ int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))",
+ 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ pr_info("drbg: Not all available DRBGs registered"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for (j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
Changes v3:
* fix invocation of drbg_sec_strength to determine the amount of seed needed
for the DRBG. The function returns information as a byte value, but the
invoker assumed a bit value.
* change default value returned by drbg_sec_strength to be the maximum entropy
defined by SP800-90A to catch erroneous invocations of the function.
* Fix invocaction of d_ops in drbg_generate: drbg->d_ops ==> shadow->d_ops
* Make return of drbg_fips_continuous_test cleaner as suggested by
Clemens Ladisch
* Fix comments on how to invoke the DRBG at the beginning of the file
* drbg_ctr_df: replace the for loop for calculation of padlen that used to
call up to 16 modulo operations with one modulo operation
* drbg_ctr_df: replace plain integer values with sizeof() to make code clearer
* drbg_hash_hashgen: replace memset() on drbg->scratchpad with memset()
on src/dst pointers to make code clearer
* as recommended by Peter Waltenberg: add re-invocation of self tests as
required by 11.3.3 -- the tests are commented out because they make no
mathematical sense. However, if a FIPS 140-2 validation requires these
tests, the code just needs to be activated.
* as recommended by Peter Waltenberg: add error path tests as required by
11.3.2 -- see new function of drbg_healthcheck_sanity
* add debug printk
* perform testing in FIPS 140-2 mode
* as recommended by Peter Waltenberg: add drbg_generate_long to generate
arbitrary long strings
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..6c866ef
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1975 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+const struct drbg_core cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static unsigned int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ if (drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_ctr_update(drbg, addtl, 1))
+ return 0;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static unsigned int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ if (drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data))
+ return 0;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ if (drbg_hmac_update(drbg, addtl, 1))
+ return 0;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static unsigned int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ unsigned int len = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ if (drbg_kcapi_hash(drbg, NULL, dst, &data)) {
+ len = 0;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static unsigned int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ if (drbg_hash_process_addtl(drbg, addtl))
+ return 0;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ if (drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1)) {
+ len = 0;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+ struct drbg_string *data2;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %lu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input) */
+ if (pers && 0 < pers->len) {
+ data2 = pers;
+ data2->next = NULL;
+ data1.next = data2;
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops are set outside, as the struct is const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside, as the struct is const */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ /* read-only data */
+ tmp->core = drbg->core;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ tmp->d_ops = drbg->d_ops;
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static unsigned int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no buffer provided\n");
+ return 0;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return 0;
+ }
+
+ if (drbg_make_shadow(drbg, &shadow)) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return 0;
+ }
+ /* 9.3.1 step 2 */
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init && shadow->d_ops->crypto_init(shadow))
+ goto err;
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ if (drbg_seed(shadow, addtl, true))
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg(pr(hmac(sha256)))",
+ "drbg(pr(hmac(sha256)))", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg(pr(ctr(aes128)))",
+ "drbg(pr(ctr(aes128)))", 0, 0);
+ else
+ err = alg_test("drbg(pr(sha256))",
+ "drbg(pr(sha256))", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /* uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static unsigned int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ unsigned int len = 0;
+ unsigned int slice = 0;
+ do {
+ unsigned int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (!tmplen)
+ return 0;
+ len += tmplen;
+ } while (slice > 0);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("drbg: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("drbg: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if (0 == memcmp(cra_name + start, cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
+#elif CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret)
+ goto outbuf;
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ if (len)
+ goto outdrbg;
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ if (len)
+ goto outdrbg;
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ if (0 == ret)
+ goto outdrbg;
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ if (!len)
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+outdrbg:
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
+ int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))",
+ 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ pr_info("drbg: Not all available DRBGs registered"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for (j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
Changes v4:
* change return codes of generate functions to signed int to convey error
codes and to match the kernel crypto API expecations on the generate
function.
* add BUG_ON throughout drbg_healthcheck_sanity() since any failure should
should be caugth to prevent the DRBG from operating
* change layout of debugging printk
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..98e3fe3
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1997 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+const struct drbg_core cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ len = ret;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data);
+ if (ret)
+ return ret;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl(drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+ struct drbg_string *data2;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %lu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input) */
+ if (pers && 0 < pers->len) {
+ data2 = pers;
+ data2->next = NULL;
+ data1.next = data2;
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops and core are set outside, as these parameters are const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside to prevent it being copied back */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* read-only data as they are defined as const, no lock needed */
+ tmp->core = drbg->core;
+ tmp->d_ops = drbg->d_ops;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no output buffer provided\n");
+ return -EINVAL;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return -EINVAL;
+ }
+
+ len = drbg_make_shadow(drbg, &shadow);
+ if (len) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return len;
+ }
+ /* 9.3.1 step 2 */
+ len = -EINVAL;
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init) {
+ len = shadow->d_ops->crypto_init(shadow);
+ if (len)
+ goto err;
+ }
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ len = drbg_seed(shadow, addtl, true);
+ if (len)
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+ if (0 >= len)
+ goto err;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg(pr(hmac(sha256)))",
+ "drbg(pr(hmac(sha256)))", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg(pr(ctr(aes128)))",
+ "drbg(pr(ctr(aes128)))", 0, 0);
+ else
+ err = alg_test("drbg(pr(sha256))",
+ "drbg(pr(sha256))", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /* uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ unsigned int slice = 0;
+ do {
+ int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (0 >= tmplen)
+ return tmplen;
+ len += tmplen;
+ } while (slice > 0);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
+ unsigned char *outval, struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if (0 == memcmp(cra_name + start, cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
+#elif CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret) {
+ rc = ret;
+ goto outbuf;
+ }
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ BUG_ON(0 < len);
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ BUG_ON(0 == ret);
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+outdrbg:
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
+ int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))",
+ 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ pr_info("DRBG: Not all available DRBGs registered"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for (j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
Changes v4:
* change return codes of generate functions to signed int to convey error
codes and to match the kernel crypto API expecations on the generate
function.
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 include/crypto/drbg.h
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
new file mode 100644
index 0000000..3fe1613
--- /dev/null
+++ b/include/crypto/drbg.h
@@ -0,0 +1,292 @@
+/*
+ * DRBG based on NIST SP800-90A
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _DRBG_H
+#define _DRBG_H
+
+
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <crypto/hash.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/slab.h> /* needed for kzalloc */
+#include <crypto/internal/rng.h>
+#include <crypto/rng.h>
+#include <linux/fips.h>
+#include <linux/spinlock.h>
+
+/*
+ * Concatenation Helper and string operation helper
+ *
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+
+struct drbg_string {
+ const unsigned char *buf;
+ size_t len;
+ struct drbg_string *next;
+};
+
+static inline void drbg_string_fill(struct drbg_string *string,
+ const unsigned char *buf, size_t len)
+{
+ string->buf = buf;
+ string->len = len;
+ string->next = NULL;
+}
+
+struct drbg_state;
+typedef uint32_t drbg_flag_t;
+
+struct drbg_core {
+ drbg_flag_t flags; /* flags for the cipher */
+ __u8 statelen; /* maximum state length */
+ __u8 max_addtllen; /* maximum length of personalization string or
+ additional input string -- exponent for base
+ 2 */
+ __u8 max_bits; /* maximum bits per RNG request -- exponent for
+ base 2*/
+ __u8 max_req; /* maximum number of requests -- exponent for
+ base 2 */
+ __u8 blocklen_bytes; /* block size of output in bytes */
+ char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
+ char cra_driver_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto
+ * API */
+ char backend_cra_name[CRYPTO_MAX_ALG_NAME]; /* kernel crypto API
+ * backend cipher name */
+};
+
+struct drbg_state_ops {
+ int (*update)(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed);
+ int (*generate)(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl);
+ int (*crypto_init)(struct drbg_state *drbg);
+ int (*crypto_fini)(struct drbg_state *drbg);
+
+};
+
+struct drbg_test_data {
+ struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */
+};
+
+struct drbg_state {
+ spinlock_t drbg_lock; /* lock around DRBG */
+ unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *C; /* hash: static value 10.1.1.1 1b)
+ * hmac / ctr: key */
+ size_t reseed_ctr; /* Number of RNG requests since last reseed --
+ * 10.1.1.1 1c) */
+ unsigned char *scratchpad; /* some memory the DRBG can use for its
+ * operation -- allocated during init */
+ void *priv_data; /* Data needed for specific cipher
+ * implementation */
+ bool seeded; /* DRBG fully seeded? */
+ bool pr; /* Prediction resistance enabled? */
+#ifdef CONFIG_CRYPTO_FIPS
+ bool fips_primed; /* Continuous test primed? */
+ unsigned char *prev; /* previous output value of DRBG_BLOCKLEN for
+ * FIPS 140-2 continuous test */
+#endif
+ const struct drbg_state_ops *d_ops;
+ const struct drbg_core *core;
+ struct drbg_test_data *test_data;
+};
+
+/* helper functions */
+static inline __u8 drbg_statelen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->statelen;
+ return 0;
+}
+
+static inline __u8 drbg_blocklen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->blocklen_bytes;
+ return 0;
+}
+
+static inline __u8 drbg_keylen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return (drbg->core->statelen - drbg->core->blocklen_bytes);
+ return 0;
+}
+
+static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
+{
+ /* max_bits is in bits, but buflen is in bytes */
+ return (1 << (drbg->core->max_bits - 3));
+}
+
+static inline size_t drbg_max_addtl(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_addtllen));
+}
+
+static inline size_t drbg_max_requests(struct drbg_state *drbg)
+{
+ return (1UL<<(drbg->core->max_req));
+}
+
+/* kernel crypto API input data structure for DRBG generate in case dlen
+ * is set to 0 */
+struct drbg_gen {
+ unsigned char *outbuf; /* output buffer for random numbers */
+ unsigned int outlen; /* size of output buffer */
+ struct drbg_string *addtl; /* input buffer for
+ * additional information string */
+ struct drbg_test_data *test_data; /* test data */
+};
+
+/*
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ struct drbg_string *addtl)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl = addtl;
+ genbuf.test_data = NULL;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_get_bytes() to allow the caller to provide additional data and
+ * allow furnishing of test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_get_bytes
+ * @outbuf output buffer -- see crypto_rng_get_bytes
+ * @outlen length of output buffer -- see crypto_rng_get_bytes
+ * @addtl_input additional information string input buffer
+ * @addtllen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_get_bytes
+ */
+static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
+ unsigned char *outbuf, unsigned int outlen,
+ struct drbg_string *addtl,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = outbuf;
+ genbuf.outlen = outlen;
+ genbuf.addtl = addtl;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/*
+ * TEST code
+ *
+ * This is a wrapper to the kernel crypto API function of
+ * crypto_rng_reset() to allow the caller to provide test_data
+ *
+ * @drng DRBG handle -- see crypto_rng_reset
+ * @pers personalization string input buffer
+ * @perslen length of additional information string buffer
+ * @test_data filled test data
+ *
+ * return
+ * see crypto_rng_reset
+ */
+static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
+ struct drbg_string *pers,
+ struct drbg_test_data *test_data)
+{
+ int ret;
+ struct drbg_gen genbuf;
+ genbuf.outbuf = NULL;
+ genbuf.outlen = 0;
+ genbuf.addtl = pers;
+ genbuf.test_data = test_data;
+ ret = crypto_rng_reset(drng, (u8 *)&genbuf, 0);
+ return ret;
+}
+
+/* DRBG type flags */
+#define DRBG_CTR ((drbg_flag_t)1<<0)
+#define DRBG_HMAC ((drbg_flag_t)1<<1)
+#define DRBG_HASH ((drbg_flag_t)1<<2)
+#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
+/* DRBG strength flags */
+#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
+#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
+#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
+#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
+ DRBG_STRENGTH256)
+
+enum drbg_prefixes {
+ DRBG_PREFIX0 = 0x00,
+ DRBG_PREFIX1,
+ DRBG_PREFIX2,
+ DRBG_PREFIX3
+};
+
+#endif /* _DRBG_H */
On Fri, 2014-04-11 at 20:07 +0200, Stephan Mueller wrote:
> Changes v4:
> * change return codes of generate functions to signed int to convey error
> codes and to match the kernel crypto API expecations on the generate
> function.
> * add BUG_ON throughout drbg_healthcheck_sanity() since any failure should
> should be caugth to prevent the DRBG from operating
> * change layout of debugging printk
It looks like const could be used a bit more often.
For instance:
perhaps uses of key could be changed to const unsigned char *key
> diff --git a/crypto/drbg.c b/crypto/drbg.c
[]
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *key,
> + unsigned char *outval, struct drbg_string *in);
[]
> +/* BCC function for CTR DRBG as defined in 10.4.3 */
> +static int drbg_ctr_bcc(struct drbg_state *drbg,
> + unsigned char *out, unsigned char *key,
> + struct drbg_string *in)
[]
> +/* Derivation Function for CTR DRBG as defined in 10.4.2 */
> +static int drbg_ctr_df(struct drbg_state *drbg,
> + unsigned char *df_data, size_t bytes_to_return,
> + struct drbg_string *addtl)
> +{
[]
> + 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";
Am Freitag, 11. April 2014, 11:20:21 schrieb Joe Perches:
Hi Joe,
>
> It looks like const could be used a bit more often.
>
> For instance:
> perhaps uses of key could be changed to const unsigned char *key
Good point. I will try to find areas where const can be used. However, due to
the use of a linked list approach with struct drbg_string, using const will
remain limited.
Ciao
Stephan
--
| Cui bono? |
Changes v5:
* make numerous character buffer pointers and drbg_string pointers const
as suggested by Joe Perches
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..1097d13
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1997 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+const struct drbg_core cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ const unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ const unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr;
+ const unsigned char *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, const unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ len = ret;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg,
+ struct drbg_string *seed, int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data);
+ if (ret)
+ return ret;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl(drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %lu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input)
+ * the variable pers is directly handed by the caller, check its
+ * contents whether it is appropriate */
+ if (pers && pers->buf && 0 < pers->len && NULL == pers->next) {
+ data1.next = pers;
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops and core are set outside, as these parameters are const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside to prevent it being copied back */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* read-only data as they are defined as const, no lock needed */
+ tmp->core = drbg->core;
+ tmp->d_ops = drbg->d_ops;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no output buffer provided\n");
+ return -EINVAL;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return -EINVAL;
+ }
+
+ len = drbg_make_shadow(drbg, &shadow);
+ if (len) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return len;
+ }
+ /* 9.3.1 step 2 */
+ len = -EINVAL;
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init) {
+ len = shadow->d_ops->crypto_init(shadow);
+ if (len)
+ goto err;
+ }
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ len = drbg_seed(shadow, addtl, true);
+ if (len)
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+ if (0 >= len)
+ goto err;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg(pr(hmac(sha256)))",
+ "drbg(pr(hmac(sha256)))", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg(pr(ctr(aes128)))",
+ "drbg(pr(ctr(aes128)))", 0, 0);
+ else
+ err = alg_test("drbg(pr(sha256))",
+ "drbg(pr(sha256))", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /* uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ unsigned int slice = 0;
+ do {
+ int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (0 >= tmplen)
+ return tmplen;
+ len += tmplen;
+ } while (slice > 0);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(cores) > i; i++) {
+ if (0 == memcmp(cra_name + start, cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
+#elif CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret) {
+ rc = ret;
+ goto outbuf;
+ }
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ BUG_ON(0 < len);
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ BUG_ON(0 == ret);
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from cores[] is used.
+ */
+static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
+ int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, cores[j].cra_name,
+ strlen(cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(cores[j].cra_name), "))",
+ 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ cores[j].cra_driver_name, strlen(cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(cores) * 2 > ARRAY_SIZE(drbg_algs))
+ pr_info("DRBG: Not all available DRBGs registered"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(cores) * 2, ARRAY_SIZE(drbg_algs));
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in cores[] twice */
+ for (j = 0; ARRAY_SIZE(cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
On Tue, 2014-04-15 at 07:35 +0200, Stephan Mueller wrote:
> diff --git a/crypto/drbg.c b/crypto/drbg.c
[]
> @@ -0,0 +1,1997 @@
[]
> +/***************************************************************
> + * Backend cipher definitions available to DRBG
> + ***************************************************************/
> +
> +const struct drbg_core cores[] = {
cores isn't a very good global name.
I presume this should be static.
Am Montag, 14. April 2014, 22:51:05 schrieb Joe Perches:
Hi Joe,
> On Tue, 2014-04-15 at 07:35 +0200, Stephan Mueller wrote:
> > diff --git a/crypto/drbg.c b/crypto/drbg.c
>
> []
>
> > @@ -0,0 +1,1997 @@
>
> []
>
> > +/***************************************************************
> > + * Backend cipher definitions available to DRBG
> > + ***************************************************************/
> > +
> > +const struct drbg_core cores[] = {
>
> cores isn't a very good global name.
> I presume this should be static.
Agreed. static added and renamed to drbg_cores. I will wait a few days before
releasing a new version. Maybe other comments show up.
Thanks for the review.
Ciao
Stephan
--
| Cui bono? |
Changes v6:
* change name of array cores to drbg_cores as suggested by Joe Perches
* make drbg_cores static as suggested by Joe Perches
* catch possible programming error regarding array overflow in drbg_algs gracefully
Signed-off-by: Stephan Mueller <[email protected]>
---
create mode 100644 crypto/drbg.c
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 0000000..cee4e1a
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,2001 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <[email protected]>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
+ !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
+ !defined(CONFIG_CRYPTO_DRBG_CTR)
+#warning "The DRBG code is useless without compiling at least one DRBG type"
+#endif
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+static const struct drbg_core drbg_cores[] = {
+ /* Hash DRBGs */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256",
+ .backend_cra_name = "sha256",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512",
+ .backend_cra_name = "sha512",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ /* HMAC DRBGs */
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes128)",
+ .cra_driver_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes192)",
+ .cra_driver_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ /* block ciphers */
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr(aes256)",
+ .cra_driver_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ const unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ const unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr;
+ const unsigned char *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, const unsigned char *key,
+ struct drbg_string *in)
+{
+ int ret = -EFAULT;
+ struct drbg_string *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ struct drbg_string data;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos) {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
+ out[cnt] ^= *pos;
+ pos++; inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos) {
+ curr = curr->next;
+ if (NULL != curr) {
+ pos = curr->buf;
+ inpos = curr->len;
+ } else {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with 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)
+ *
+ * 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_keylen(drbg) + drbg_blocklen(drbg) ==
+ * drbg_statelen(drbg))
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct drbg_string *addtl)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ struct drbg_string *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ 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;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 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 */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ drbg_string_fill(&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+ /* splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain */
+ tempstr = addtl;
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ if (NULL == tempstr->next)
+ break;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /* 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 */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ 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 -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function of CTR DRBG as defined in 10.2.1.2 */
+static int drbg_ctr_update(struct drbg_state *drbg,
+ struct drbg_string *addtl, int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
+ addtl);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
+ * all memory during initialization */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /* 10.2.1.2 step 2.2 */
+ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ /*TODO the DF function is called again since according to step
+ * 2, the "additional_input" after step 2 is the output of the DF
+ * function -- when we save the DF output as a replacement
+ * for the addtl_input data, we do not need to call the DF again here */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_ctr_update(drbg, addtl, 1);
+ if (ret)
+ len = ret;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg,
+ struct drbg_string *seed, int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, cipherin;
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len) {
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data);
+ if (ret)
+ return ret;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct drbg_string *entropy)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data1;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ } else {
+ drbg_string_fill(&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct drbg_string *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ struct drbg_string *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* use the scratchpad as a lookaside buffer */
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+
+ /*
+ * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
+ * fully completes before returning. Thus, we can reuse the scratchpad
+ */
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl(drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ data1.next = &data2;
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %lu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input)
+ * the variable pers is directly handed by the caller, check its
+ * contents whether it is appropriate */
+ if (pers && pers->buf && 0 < pers->len && NULL == pers->next) {
+ data1.next = pers;
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &data1, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/*
+ * Free all substructures in a DRBG state without the DRBG state structure
+ */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state
+ * The DRBG state structure must already be allocated
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+
+/*
+ * Copy the DRBG state
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ /* no copy of scratchpad */
+ /* priv_data is initialized with call to crypto_init */
+ /* d_ops and core are set outside, as these parameters are const */
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /* test_data is set outside to prevent it being copied back */
+}
+/*
+ * Generate shadow copy of the DRBG state
+ */
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ /* some sanity checks */
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* read-only data as they are defined as const, no lock needed */
+ tmp->core = drbg->core;
+ tmp->d_ops = drbg->d_ops;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+/*
+ * Restore shadow state into original DRBG state
+ */
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ struct drbg_state *shadow = NULL;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no output buffer provided\n");
+ return -EINVAL;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return -EINVAL;
+ }
+
+ len = drbg_make_shadow(drbg, &shadow);
+ if (len) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return len;
+ }
+ /* 9.3.1 step 2 */
+ len = -EINVAL;
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init) {
+ len = shadow->d_ops->crypto_init(shadow);
+ if (len)
+ goto err;
+ }
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ len = drbg_seed(shadow, addtl, true);
+ if (len)
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+ if (0 >= len)
+ goto err;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg(pr(hmac(sha256)))",
+ "drbg(pr(hmac(sha256)))", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg(pr(ctr(aes128)))",
+ "drbg(pr(ctr(aes128)))", 0, 0);
+ else
+ err = alg_test("drbg(pr(sha256))",
+ "drbg(pr(sha256))", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /* uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ unsigned int slice = 0;
+ do {
+ int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (0 >= tmplen)
+ return tmplen;
+ len += tmplen;
+ } while (slice > 0);
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &drbg_cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ /* no allocation of drbg as this is done by the kernel crypto API */
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ /* allocate cipher handle */
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed(drbg, pers, false);
+ /* deallocate cipher handle */
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ /* no freeing of drbg as this is done by the kernel crypto API */
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto APi cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ for (; NULL != in; in = in->next)
+ crypto_shash_update(&sdesc->shash, in->buf, in->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* in is only component */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the drbg_cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part and the closing parenthesis */
+ len = strlen(cra_name) - start - 2;
+ for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
+ if (0 == memcmp(cra_name + start,
+ drbg_cores[i].cra_name, len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+/*
+ * Initialize one DRBG invoked by the kernel crypto API
+ *
+ * Function uses the kernel crypto API cra_name to look up
+ * the flags to instantiate the DRBG
+ */
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
+ /* when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ *
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ data->addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ return drbg_instantiate(drbg, data->addtl, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ unsigned int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
+#elif CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret) {
+ rc = ret;
+ goto outbuf;
+ }
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ BUG_ON(0 < len);
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ BUG_ON(0 == ret);
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from drbg_cores[] is used.
+ */
+static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
+ int pr)
+{
+ int pos = 0;
+
+ memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
+ if (pr) {
+ memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
+ memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(drbg_algs[i].cra_name + pos, drbg_cores[j].cra_name,
+ strlen(drbg_cores[j].cra_name));
+ memcpy(drbg_algs[i].cra_name + pos + strlen(drbg_cores[j].cra_name),
+ "))", 2);
+ memcpy(drbg_algs[i].cra_driver_name + pos,
+ drbg_cores[j].cra_driver_name,
+ strlen(drbg_cores[j].cra_driver_name));
+ drbg_algs[i].cra_priority = 100;
+ drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
+ drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
+ drbg_algs[i].cra_type = &crypto_rng_type;
+ drbg_algs[i].cra_module = THIS_MODULE;
+ drbg_algs[i].cra_init = drbg_kcapi_init;
+ drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
+ drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
+ drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
+ drbg_algs[i].cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to drbg_cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
+ pr_info("DRBG: Cannot register all DRBG types"
+ "(slots needed: %lu, slots available: %lu)\n",
+ ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
+ return ret;
+ }
+
+ /* each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in drbg_cores[] twice */
+ for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++) {
+ drbg_fill_array(i, j, 1);
+ i++;
+ drbg_fill_array(i, j, 0);
+ i++;
+ }
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+"HMAC "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+"Hash "
+#endif
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+"CTR"
+#endif
+);
On Sat, Apr 26, 2014 at 10:13:08PM +0200, Stephan Mueller wrote:
> Changes v6:
> * change name of array cores to drbg_cores as suggested by Joe Perches
> * make drbg_cores static as suggested by Joe Perches
> * catch possible programming error regarding array overflow in drbg_algs gracefully
>
> Signed-off-by: Stephan Mueller <[email protected]>
> ---
> create mode 100644 crypto/drbg.c
>
> diff --git a/crypto/drbg.c b/crypto/drbg.c
> new file mode 100644
> index 0000000..cee4e1a
> --- /dev/null
> +++ b/crypto/drbg.c
> @@ -0,0 +1,2001 @@
> +/*
> + * DRBG: Deterministic Random Bits Generator
> + * Based on NIST Recommended DRBG from NIST SP800-90A with the following
> + * properties:
> + * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
> + * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
> + * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
> + * * with and without prediction resistance
> + *
> + * Copyright Stephan Mueller <[email protected]>, 2014
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, and the entire permission notice in its entirety,
> + * including the disclaimer of warranties.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote
> + * products derived from this software without specific prior
> + * written permission.
> + *
> + * ALTERNATIVELY, this product may be distributed under the terms of
> + * the GNU General Public License, in which case the provisions of the GPL are
> + * required INSTEAD OF the above restrictions. (This clause is
> + * necessary due to a potential bad interaction between the GPL and
> + * the restrictions contained in a BSD-style copyright.)
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * DRBG Usage
> + * ==========
> + * The SP 800-90A DRBG allows the user to specify a personalization string
> + * for initialization as well as an additional information string for each
> + * random number request. The following code fragments show how a caller
> + * uses the kernel crypto API to use the full functionality of the DRBG.
> + *
> + * Usage without any additional data
> + * ---------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + *
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * err = crypto_rng_get_bytes(drng, &data, DATALEN);
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with personalization string during initialization
> + * -------------------------------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + * struct drbg_string pers;
> + * char personalization[11] = "some-string";
> + *
> + * drbg_string_fill(&pers, personalization, strlen(personalization));
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * // The reset completely re-initializes the DRBG with the provided
> + * // personalization string
> + * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
> + * err = crypto_rng_get_bytes(drng, &data, DATALEN);
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with additional information string during random number request
> + * ---------------------------------------------------------------------
> + * struct crypto_rng *drng;
> + * int err;
> + * char data[DATALEN];
> + * char addtl_string[11] = "some-string";
> + * string drbg_string addtl;
> + *
> + * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
> + * drng = crypto_alloc_rng(drng_name, 0, 0);
> + * // The following call is a wrapper to crypto_rng_get_bytes() and returns
> + * // the same error codes.
> + * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
> + * crypto_free_rng(drng);
> + *
> + *
> + * Usage with personalization and additional information strings
> + * -------------------------------------------------------------
> + * Just mix both scenarios above.
> + */
> +
> +#include <crypto/drbg.h>
> +
> +#if !defined(CONFIG_CRYPTO_DRBG_HASH) && \
> + !defined(CONFIG_CRYPTO_DRBG_HMAC) && \
> + !defined(CONFIG_CRYPTO_DRBG_CTR)
> +#warning "The DRBG code is useless without compiling at least one DRBG type"
> +#endif
> +
> +/***************************************************************
> + * Backend cipher definitions available to DRBG
> + ***************************************************************/
> +
> +static const struct drbg_core drbg_cores[] = {
> + /* Hash DRBGs */
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> + {
> + .flags = DRBG_HASH | DRBG_STRENGTH128,
> + .statelen = 55, /* 440 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 20,
> + .cra_name = "sha1",
> + .cra_driver_name = "sha1",
> + .backend_cra_name = "sha1",
> + }, {
> + .flags = DRBG_HASH | DRBG_STRENGTH256,
> + .statelen = 55, /* 440 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 32,
> + .cra_name = "sha256",
> + .cra_driver_name = "sha256",
> + .backend_cra_name = "sha256",
> + }, {
> + .flags = DRBG_HASH | DRBG_STRENGTH256,
> + .statelen = 111, /* 888 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 48,
> + .cra_name = "sha384",
> + .cra_driver_name = "sha384",
> + .backend_cra_name = "sha384",
> + }, {
> + .flags = DRBG_HASH | DRBG_STRENGTH256,
> + .statelen = 111, /* 888 bits */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 64,
> + .cra_name = "sha512",
> + .cra_driver_name = "sha512",
> + .backend_cra_name = "sha512",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> + {
> + /* HMAC DRBGs */
> + .flags = DRBG_HMAC | DRBG_STRENGTH256,
> + .statelen = 20, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 20,
> + .cra_name = "hmac(sha1)",
> + .cra_driver_name = "hmac_sha1",
> + .backend_cra_name = "hmac(sha1)",
> + }, {
> + .flags = DRBG_HMAC | DRBG_STRENGTH256,
> + .statelen = 32, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 32,
> + .cra_name = "hmac(sha256)",
> + .cra_driver_name = "hmac_sha256",
> + .backend_cra_name = "hmac(sha256)",
> + }, {
> + .flags = DRBG_HMAC | DRBG_STRENGTH256,
> + .statelen = 48, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 48,
> + .cra_name = "hmac(sha384)",
> + .cra_driver_name = "hmac_sha384",
> + .backend_cra_name = "hmac(sha384)",
> + }, {
> + .flags = DRBG_HMAC | DRBG_STRENGTH256,
> + .statelen = 64, /* block length of cipher */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 64,
> + .cra_name = "hmac(sha512)",
> + .cra_driver_name = "hmac_sha512",
> + .backend_cra_name = "hmac(sha512)",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> + {
> + /* block ciphers */
> + .flags = DRBG_CTR | DRBG_STRENGTH128,
> + .statelen = 32, /* 256 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cra_name = "ctr(aes128)",
> + .cra_driver_name = "ctr_aes128",
> + .backend_cra_name = "ecb(aes)",
> + }, {
> + /* block ciphers */
> + .flags = DRBG_CTR | DRBG_STRENGTH192,
> + .statelen = 40, /* 320 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cra_name = "ctr(aes192)",
> + .cra_driver_name = "ctr_aes192",
> + .backend_cra_name = "ecb(aes)",
> + }, {
> + /* block ciphers */
> + .flags = DRBG_CTR | DRBG_STRENGTH256,
> + .statelen = 48, /* 384 bits as defined in 10.2.1 */
> + .max_addtllen = 35,
> + .max_bits = 19,
> + .max_req = 48,
> + .blocklen_bytes = 16,
> + .cra_name = "ctr(aes256)",
> + .cra_driver_name = "ctr_aes256",
> + .backend_cra_name = "ecb(aes)",
> + },
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +};
> +
> +/******************************************************************
> + * Generic helper functions
> + ******************************************************************/
> +
> +/*
> + * Return strength of DRBG according to SP800-90A section 8.4
> + *
> + * @flags DRBG flags reference
> + *
> + * Return: normalized strength in *bytes* value or 32 as default
> + * to counter programming errors
> + */
> +static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
> +{
> + switch (flags & DRBG_STRENGTH_MASK) {
> + case DRBG_STRENGTH128:
> + return 16;
> + case DRBG_STRENGTH192:
> + return 24;
> + case DRBG_STRENGTH256:
> + return 32;
> + default:
> + return 32;
> + }
> +}
> +
> +/*
> + * FIPS 140-2 continuous self test
> + * The test is performed on the result of one round of the output
> + * function. Thus, the function implicitly knows the size of the
> + * buffer.
> + *
> + * The FIPS test can be called in an endless loop until it returns
> + * true. Although the code looks like a potential for a deadlock, it
> + * is not the case, because returning a false cannot mathematically
> + * occur (except once when a reseed took place and the updated state
> + * would is now set up such that the generation of new value returns
> + * an identical one -- this is most unlikely and would happen only once).
> + * Thus, if this function repeatedly returns false and thus would cause
> + * a deadlock, the integrity of the entire kernel is lost.
> + *
> + * @drbg DRBG handle
> + * @buf output buffer of random data to be checked
> + *
> + * return:
> + * true on success
> + * false on error
> + */
> +static bool drbg_fips_continuous_test(struct drbg_state *drbg,
> + const unsigned char *buf)
> +{
> +#ifdef CONFIG_CRYPTO_FIPS
> + int ret = 0;
> + /* skip test if we test the overall system */
> + if (drbg->test_data)
> + return true;
> + /* only perform test in FIPS mode */
> + if (0 == fips_enabled)
> + return true;
> + if (!drbg->fips_primed) {
> + /* Priming of FIPS test */
> + memcpy(drbg->prev, buf, drbg_blocklen(drbg));
> + drbg->fips_primed = true;
> + /* return false due to priming, i.e. another round is needed */
> + return false;
> + }
> + ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
> + memcpy(drbg->prev, buf, drbg_blocklen(drbg));
> + /* the test shall pass when the two compared values are not equal */
> + return ret != 0;
> +#else
> + return true;
> +#endif /* CONFIG_CRYPTO_FIPS */
> +}
> +
> +/*
> + * Convert an integer into a byte representation of this integer.
> + * The byte representation is big-endian
> + *
> + * @buf buffer holding the converted integer
> + * @val value to be converted
> + * @buflen length of buffer
> + */
> +#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
> +static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
> + size_t buflen)
> +{
> + unsigned char *byte;
> + uint64_t i;
> +
> + byte = buf + (buflen - 1);
> + for (i = 0; i < buflen; i++)
> + *(byte--) = val >> (i * 8) & 0xff;
> +}
> +
> +/*
> + * Increment buffer
> + *
> + * @dst buffer to increment
> + * @add value to add
> + */
> +static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
> + const unsigned char *add, size_t addlen)
> +{
> + /* implied: dstlen > addlen */
> + unsigned char *dstptr;
> + const unsigned char *addptr;
> + unsigned int remainder = 0;
> + size_t len = addlen;
> +
> + dstptr = dst + (dstlen-1);
> + addptr = add + (addlen-1);
> + while (len) {
> + remainder += *dstptr + *addptr;
> + *dstptr = remainder & 0xff;
> + remainder >>= 8;
> + len--; dstptr--; addptr--;
> + }
> + len = dstlen - addlen;
> + while (len && remainder > 0) {
> + remainder = *dstptr + 1;
> + *dstptr = remainder & 0xff;
> + remainder >>= 8;
> + len--; dstptr--;
> + }
> +}
> +#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
> +
> +/******************************************************************
> + * CTR DRBG callback functions
> + ******************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
> + unsigned char *outval, const struct drbg_string *in);
> +static int drbg_init_sym_kernel(struct drbg_state *drbg);
> +static int drbg_fini_sym_kernel(struct drbg_state *drbg);
> +
> +/* BCC function for CTR DRBG as defined in 10.4.3 */
> +static int drbg_ctr_bcc(struct drbg_state *drbg,
> + unsigned char *out, const unsigned char *key,
> + struct drbg_string *in)
> +{
> + int ret = -EFAULT;
> + struct drbg_string *curr = in;
> + size_t inpos = curr->len;
> + const unsigned char *pos = curr->buf;
> + struct drbg_string data;
> +
> + drbg_string_fill(&data, out, drbg_blocklen(drbg));
> +
> + /* 10.4.3 step 1 */
> + memset(out, 0, drbg_blocklen(drbg));
> +
> + /* 10.4.3 step 2 / 4 */
> + while (inpos) {
> + short cnt = 0;
> + /* 10.4.3 step 4.1 */
> + for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
> + out[cnt] ^= *pos;
> + pos++; inpos--;
> + /* the following branch implements the linked list
> + * iteration. If we are at the end of the current data
> + * set, we have to start using the next data set if
> + * available -- the inpos value always points to the
> + * current byte and will be zero if we have processed
> + * the last byte of the last linked list member */
> + if (0 == inpos) {
> + curr = curr->next;
> + if (NULL != curr) {
> + pos = curr->buf;
> + inpos = curr->len;
> + } else {
> + inpos = 0;
> + break;
> + }
> + }
> + }
> + /* 10.4.3 step 4.2 */
> + ret = drbg_kcapi_sym(drbg, key, out, &data);
> + if (ret)
> + return ret;
> + /* 10.4.3 step 2 */
> + }
> + return 0;
> +}
> +
> +/*
> + * scratchpad usage: drbg_ctr_update is interlinked with 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)
> + *
> + * 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_keylen(drbg) + drbg_blocklen(drbg) ==
> + * drbg_statelen(drbg))
> + */
> +
> +/* Derivation Function for CTR DRBG as defined in 10.4.2 */
> +static int drbg_ctr_df(struct drbg_state *drbg,
> + unsigned char *df_data, size_t bytes_to_return,
> + struct drbg_string *addtl)
> +{
> + int ret = -EFAULT;
> + unsigned char L_N[8];
> + /* S3 is input */
> + struct drbg_string S1, S2, S4, cipherin;
> + struct drbg_string *tempstr = addtl;
> + unsigned char *pad = df_data + drbg_statelen(drbg);
> + unsigned char *iv = pad + drbg_blocklen(drbg);
> + unsigned char *temp = iv + drbg_blocklen(drbg);
> + 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;
> +
> + memset(pad, 0, drbg_blocklen(drbg));
> + memset(iv, 0, drbg_blocklen(drbg));
> + memset(temp, 0, drbg_statelen(drbg));
> +
> + /* 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 */
> + for (; NULL != tempstr; tempstr = tempstr->next)
> + inputlen += tempstr->len;
> + drbg_int2byte(&L_N[0], inputlen, 4);
> +
> + /* 10.4.2 step 3 */
> + drbg_int2byte(&L_N[4], bytes_to_return, 4);
> +
> + /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
> + padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
> + /* wrap the padlen appropriately */
> + if (padlen)
> + padlen = drbg_blocklen(drbg) - padlen;
> + /* pad / padlen contains the 0x80 byte and the following zero bytes, so
> + * add one for byte for 0x80 */
weird multiline commentary style above, better switch to the standard:
/*
* line a
* line b
*/
> + padlen++;
> + pad[0] = 0x80;
> +
> + /* 10.4.2 step 4 -- first fill the linked list and then order it */
> + drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
> + drbg_string_fill(&S2, L_N, sizeof(L_N));
> + drbg_string_fill(&S4, pad, padlen);
> + S1.next = &S2;
> + S2.next = addtl;
> + /* splice in addtl between S2 and S4 -- we place S4 at the end of the
> + * input data chain */
ditto
> + tempstr = addtl;
> + for (; NULL != tempstr; tempstr = tempstr->next)
> + if (NULL == tempstr->next)
> + break;
> + tempstr->next = &S4;
> +
> + /* 10.4.2 step 9 */
> + while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
> + /* 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 */
ditto
> + drbg_int2byte(iv, i, 4);
> + /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
> + ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
> + if (ret)
> + goto out;
> + /* 10.4.2 step 9.3 */
> + i++;
> + templen += drbg_blocklen(drbg);
> + }
> +
> + /* 10.4.2 step 11 */
> + /* implicit key len with seedlen - blocklen according to table 3 */
ditto
> + X = temp + (drbg_keylen(drbg));
> + drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
> +
> + /* 10.4.2 step 12: overwriting of outval */
> +
> + /* 10.4.2 step 13 */
ditto
Well, I won't go down pointing to every single occurrence of
new-and-out-of-standard multiline comments. Yeah, these are nitpicks,
but coding style is something we must strive to keep consistent accross
such big project as the linux kernel. Please, review your code and
adjust its style according to Documentation/CodingStyle.
Also, please consider doing a fresh re-submission of all your patches
(with respecting changelogs) as it's getting confusing to identify what
needs reviewer follow up on this thread.
Regards!
-- Rafael
> + 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 -- check for the implementation
> + * of the cipher function callback */
> + ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
> + if (ret)
> + goto out;
> + blocklen = (drbg_blocklen(drbg) <
> + (bytes_to_return - generated_len)) ?
> + drbg_blocklen(drbg) :
> + (bytes_to_return - generated_len);
> + /* 10.4.2 step 13.2 and 14 */
> + memcpy(df_data + generated_len, X, blocklen);
> + generated_len += blocklen;
> + }
> +
> + ret = 0;
> +
> +out:
> + memset(iv, 0, drbg_blocklen(drbg));
> + memset(temp, 0, drbg_statelen(drbg));
> + memset(pad, 0, drbg_blocklen(drbg));
> + return ret;
> +}
> +
> +/* update function of CTR DRBG as defined in 10.2.1.2 */
> +static int drbg_ctr_update(struct drbg_state *drbg,
> + struct drbg_string *addtl, int reseed)
> +{
> + int ret = -EFAULT;
> + /* 10.2.1.2 step 1 */
> + unsigned char *temp = drbg->scratchpad;
> + unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
> + drbg_blocklen(drbg);
> + unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
> + unsigned int len = 0;
> + struct drbg_string cipherin;
> + unsigned char prefix = DRBG_PREFIX1;
> +
> + memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
> + memset(df_data, 0, drbg_statelen(drbg));
> +
> + /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
> + if (addtl && 0 < addtl->len) {
> + ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
> + addtl);
> + if (ret)
> + goto out;
> + }
> +
> + drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
> + /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0)
> + * all memory during initialization */
> + while (len < (drbg_statelen(drbg))) {
> + /* 10.2.1.2 step 2.1 */
> + drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
> + /* 10.2.1.2 step 2.2 */
> + /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */
> + ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
> + if (ret)
> + goto out;
> + /* 10.2.1.2 step 2.3 and 3 */
> + len += drbg_blocklen(drbg);
> + }
> +
> + /* 10.2.1.2 step 4 */
> + temp_p = temp;
> + df_data_p = df_data;
> + for (len = 0; len < drbg_statelen(drbg); len++) {
> + *temp_p ^= *df_data_p;
> + df_data_p++; temp_p++;
> + }
> +
> + /* 10.2.1.2 step 5 */
> + memcpy(drbg->C, temp, drbg_keylen(drbg));
> + /* 10.2.1.2 step 6 */
> + memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
> + ret = 0;
> +
> +out:
> + memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
> + memset(df_data, 0, drbg_statelen(drbg));
> + return ret;
> +}
> +
> +/*
> + * scratchpad use: drbg_ctr_update is called independently from
> + * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
> + */
> +/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
> +static int drbg_ctr_generate(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + int len = 0;
> + int ret = 0;
> + struct drbg_string data;
> + unsigned char prefix = DRBG_PREFIX1;
> +
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> +
> + /* 10.2.1.5.2 step 2 */
> + if (addtl && 0 < addtl->len) {
> + addtl->next = NULL;
> + ret = drbg_ctr_update(drbg, addtl, 1);
> + if (ret)
> + return 0;
> + }
> +
> + /* 10.2.1.5.2 step 4.1 */
> + drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
> + drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
> + while (len < buflen) {
> + int outlen = 0;
> + /* 10.2.1.5.2 step 4.2 */
> + ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
> + if (ret) {
> + len = ret;
> + goto out;
> + }
> + outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
> + drbg_blocklen(drbg) : (buflen - len);
> + if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
> + /* 10.2.1.5.2 step 6 */
> + drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
> + continue;
> + }
> + /* 10.2.1.5.2 step 4.3 */
> + memcpy(buf + len, drbg->scratchpad, outlen);
> + len += outlen;
> + /* 10.2.1.5.2 step 6 */
> + if (len < buflen)
> + drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
> + }
> +
> + /* 10.2.1.5.2 step 6 */
> + /*TODO the DF function is called again since according to step
> + * 2, the "additional_input" after step 2 is the output of the DF
> + * function -- when we save the DF output as a replacement
> + * for the addtl_input data, we do not need to call the DF again here */
> + if (addtl)
> + addtl->next = NULL;
> + ret = drbg_ctr_update(drbg, addtl, 1);
> + if (ret)
> + len = ret;
> +
> +out:
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> + return len;
> +}
> +
> +static struct drbg_state_ops drbg_ctr_ops = {
> + .update = drbg_ctr_update,
> + .generate = drbg_ctr_generate,
> + .crypto_init = drbg_init_sym_kernel,
> + .crypto_fini = drbg_fini_sym_kernel,
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +
> +/******************************************************************
> + * HMAC DRBG callback functions
> + ******************************************************************/
> +
> +#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
> +static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
> + unsigned char *outval, const struct drbg_string *in);
> +static int drbg_init_hash_kernel(struct drbg_state *drbg);
> +static int drbg_fini_hash_kernel(struct drbg_state *drbg);
> +#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +/* update function of HMAC DRBG as defined in 10.1.2.2 */
> +static int drbg_hmac_update(struct drbg_state *drbg,
> + struct drbg_string *seed, int reseed)
> +{
> + int ret = -EFAULT;
> + int i = 0;
> + struct drbg_string seed1, seed2, cipherin;
> +
> + if (!reseed) {
> + /* 10.1.2.3 step 2 already implicitly covered with
> + * the initial memset(0) of drbg->C */
> + memset(drbg->C, 0, drbg_statelen(drbg));
> + memset(drbg->V, 1, drbg_statelen(drbg));
> + }
> +
> + /* build linked list which implements the concatenation and fill
> + * first part*/
> + drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
> + /* buffer will be filled in for loop below with one byte */
> + drbg_string_fill(&seed2, NULL, 1);
> + seed1.next = &seed2;
> + /* seed may be NULL */
> + seed2.next = seed;
> +
> + drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
> + /* we execute two rounds of V/K massaging */
> + for (i = 2; 0 < i; i--) {
> + /* first round uses 0x0, second 0x1 */
> + unsigned char prefix = DRBG_PREFIX0;
> + if (1 == i)
> + prefix = DRBG_PREFIX1;
> + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
> + seed2.buf = &prefix;
> + ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
> + if (ret)
> + return ret;
> +
> + /* 10.1.2.2 step 2 and 5 -- HMAC for V */
> + ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
> + if (ret)
> + return ret;
> +
> + /* 10.1.2.2 step 3 */
> + if (!seed || 0 == seed->len)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/* generate function of HMAC DRBG as defined in 10.1.2.5 */
> +static int drbg_hmac_generate(struct drbg_state *drbg,
> + unsigned char *buf,
> + unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + int len = 0;
> + int ret = 0;
> + struct drbg_string data;
> +
> + /* 10.1.2.5 step 2 */
> + if (addtl && 0 < addtl->len) {
> + addtl->next = NULL;
> + ret = drbg_hmac_update(drbg, addtl, 1);
> + if (ret)
> + return ret;
> + }
> +
> + drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
> + while (len < buflen) {
> + unsigned int outlen = 0;
> + /* 10.1.2.5 step 4.1 */
> + ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data);
> + if (ret)
> + return ret;
> + outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
> + drbg_blocklen(drbg) : (buflen - len);
> + if (!drbg_fips_continuous_test(drbg, drbg->V))
> + continue;
> +
> + /* 10.1.2.5 step 4.2 */
> + memcpy(buf + len, drbg->V, outlen);
> + len += outlen;
> + }
> +
> + /* 10.1.2.5 step 6 */
> + if (addtl)
> + addtl->next = NULL;
> + ret = drbg_hmac_update(drbg, addtl, 1);
> + if (ret)
> + return ret;
> +
> + return len;
> +}
> +
> +static struct drbg_state_ops drbg_hmac_ops = {
> + .update = drbg_hmac_update,
> + .generate = drbg_hmac_generate,
> + .crypto_init = drbg_init_hash_kernel,
> + .crypto_fini = drbg_fini_hash_kernel,
> +
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +
> +/******************************************************************
> + * Hash DRBG callback functions
> + ******************************************************************/
> +
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> +/*
> + * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
> + * interlinked, the scratchpad is used as follows:
> + * drbg_hash_update
> + * start: drbg->scratchpad
> + * length: drbg_statelen(drbg)
> + * drbg_hash_df:
> + * start: drbg->scratchpad + drbg_statelen(drbg)
> + * length: drbg_blocklen(drbg)
> + */
> +/* Derivation Function for Hash DRBG as defined in 10.4.1 */
> +static int drbg_hash_df(struct drbg_state *drbg,
> + unsigned char *outval, size_t outlen,
> + struct drbg_string *entropy)
> +{
> + int ret = 0;
> + size_t len = 0;
> + unsigned char input[5];
> + unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
> + struct drbg_string data1;
> +
> + memset(tmp, 0, drbg_blocklen(drbg));
> +
> + /* 10.4.1 step 3 */
> + input[0] = 1;
> + drbg_int2byte(&input[1], (outlen * 8), 4);
> +
> + /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
> + drbg_string_fill(&data1, input, 5);
> + data1.next = entropy;
> +
> + /* 10.4.1 step 4 */
> + while (len < outlen) {
> + short blocklen = 0;
> + /* 10.4.1 step 4.1 */
> + ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
> + if (ret)
> + goto out;
> + /* 10.4.1 step 4.2 */
> + input[0]++;
> + blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
> + drbg_blocklen(drbg) : (outlen - len);
> + memcpy(outval + len, tmp, blocklen);
> + len += blocklen;
> + }
> +
> +out:
> + memset(tmp, 0, drbg_blocklen(drbg));
> + return ret;
> +}
> +
> +/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
> +static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
> + int reseed)
> +{
> + int ret = 0;
> + struct drbg_string data1, data2;
> + unsigned char *V = drbg->scratchpad;
> + unsigned char prefix = DRBG_PREFIX1;
> +
> + memset(drbg->scratchpad, 0, drbg_statelen(drbg));
> + if (!seed)
> + return -EINVAL;
> +
> + if (reseed) {
> + /* 10.1.1.3 step 1: string length is concatenation of
> + * 1 byte, V and seed (which is concatenated entropy/addtl
> + * input)
> + */
> + memcpy(V, drbg->V, drbg_statelen(drbg));
> + drbg_string_fill(&data1, &prefix, 1);
> + drbg_string_fill(&data2, V, drbg_statelen(drbg));
> + data1.next = &data2;
> + data2.next = seed;
> + } else {
> + drbg_string_fill(&data1, seed->buf, seed->len);
> + data1.next = seed->next;
> + }
> +
> + /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
> + ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
> + if (ret)
> + goto out;
> +
> + /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
> + prefix = DRBG_PREFIX0;
> + drbg_string_fill(&data1, &prefix, 1);
> + drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
> + data1.next = &data2;
> + /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
> + ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
> +
> +out:
> + memset(drbg->scratchpad, 0, drbg_statelen(drbg));
> + return ret;
> +}
> +
> +/* processing of additional information string for Hash DRBG */
> +static int drbg_hash_process_addtl(struct drbg_state *drbg,
> + struct drbg_string *addtl)
> +{
> + int ret = 0;
> + struct drbg_string data1, data2;
> + struct drbg_string *data3;
> + unsigned char prefix = DRBG_PREFIX2;
> +
> + /* this is value w as per documentation */
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> +
> + /* 10.1.1.4 step 2 */
> + if (!addtl || 0 == addtl->len)
> + return 0;
> +
> + /* 10.1.1.4 step 2a -- concatenation */
> + drbg_string_fill(&data1, &prefix, 1);
> + drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
> + data3 = addtl;
> + data1.next = &data2;
> + data2.next = data3;
> + data3->next = NULL;
> + /* 10.1.1.4 step 2a -- cipher invocation */
> + ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
> + if (ret)
> + goto out;
> +
> + /* 10.1.1.4 step 2b */
> + drbg_add_buf(drbg->V, drbg_statelen(drbg),
> + drbg->scratchpad, drbg_blocklen(drbg));
> +
> +out:
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> + return ret;
> +}
> +
> +/*
> + * Hashgen defined in 10.1.1.4
> + */
> +static int drbg_hash_hashgen(struct drbg_state *drbg,
> + unsigned char *buf,
> + unsigned int buflen)
> +{
> + int len = 0;
> + int ret = 0;
> + unsigned char *src = drbg->scratchpad;
> + unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
> + struct drbg_string data;
> + unsigned char prefix = DRBG_PREFIX1;
> +
> + /* use the scratchpad as a lookaside buffer */
> + memset(src, 0, drbg_statelen(drbg));
> + memset(dst, 0, drbg_blocklen(drbg));
> +
> + /* 10.1.1.4 step hashgen 2 */
> + memcpy(src, drbg->V, drbg_statelen(drbg));
> +
> + drbg_string_fill(&data, src, drbg_statelen(drbg));
> + while (len < buflen) {
> + unsigned int outlen = 0;
> + /* 10.1.1.4 step hashgen 4.1 */
> + ret = drbg_kcapi_hash(drbg, NULL, dst, &data);
> + if (ret) {
> + len = ret;
> + goto out;
> + }
> + outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
> + drbg_blocklen(drbg) : (buflen - len);
> + if (!drbg_fips_continuous_test(drbg, dst)) {
> + drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
> + continue;
> + }
> + /* 10.1.1.4 step hashgen 4.2 */
> + memcpy(buf + len, dst, outlen);
> + len += outlen;
> + /* 10.1.1.4 hashgen step 4.3 */
> + if (len < buflen)
> + drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
> + }
> +
> +out:
> + memset(drbg->scratchpad, 0,
> + (drbg_statelen(drbg) + drbg_blocklen(drbg)));
> + return len;
> +}
> +
> +/* generate function for Hash DRBG as defined in 10.1.1.4 */
> +static int drbg_hash_generate(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + int len = 0;
> + int ret = 0;
> + unsigned char req[8];
> + unsigned char prefix = DRBG_PREFIX3;
> + struct drbg_string data1, data2;
> +
> + /*
> + * scratchpad usage: drbg_hash_process_addtl uses the scratchpad, but
> + * fully completes before returning. Thus, we can reuse the scratchpad
> + */
> + /* 10.1.1.4 step 2 */
> + ret = drbg_hash_process_addtl(drbg, addtl);
> + if (ret)
> + return ret;
> + /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
> + * 10.1.1.4 */
> + len = drbg_hash_hashgen(drbg, buf, buflen);
> +
> + /* this is the value H as documented in 10.1.1.4 */
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> + /* 10.1.1.4 step 4 */
> + drbg_string_fill(&data1, &prefix, 1);
> + drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
> + data1.next = &data2;
> + ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
> + if (ret) {
> + len = ret;
> + goto out;
> + }
> +
> + /* 10.1.1.4 step 5 */
> + drbg_add_buf(drbg->V, drbg_statelen(drbg),
> + drbg->scratchpad, drbg_blocklen(drbg));
> + drbg_add_buf(drbg->V, drbg_statelen(drbg),
> + drbg->C, drbg_statelen(drbg));
> + drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
> + drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
> +
> +out:
> + memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
> + return len;
> +}
> +
> +/*
> + * scratchpad usage: as update and generate are used isolated, both
> + * can use the scratchpad
> + */
> +static struct drbg_state_ops drbg_hash_ops = {
> + .update = drbg_hash_update,
> + .generate = drbg_hash_generate,
> + .crypto_init = drbg_init_hash_kernel,
> + .crypto_fini = drbg_fini_hash_kernel,
> +};
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +
> +/******************************************************************
> + * Functions common for DRBG implementations
> + ******************************************************************/
> +
> +/*
> + * Seeding or reseeding of the DRBG
> + *
> + * @drbg: DRBG state struct
> + * @pers: personalization / additional information buffer
> + * @reseed: 0 for initial seed process, 1 for reseeding
> + *
> + * return:
> + * 0 on success
> + * error value otherwise
> + */
> +static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
> + bool reseed)
> +{
> + int ret = 0;
> + unsigned char *entropy = NULL;
> + size_t entropylen = 0;
> + struct drbg_string data1;
> +
> + /* 9.1 / 9.2 / 9.3.1 step 3 */
> + if (pers && pers->len > (drbg_max_addtl(drbg))) {
> + pr_devel("DRBG: personalization string too long %lu\n",
> + pers->len);
> + return -EINVAL;
> + }
> +
> + if (drbg->test_data && drbg->test_data->testentropy) {
> + drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
> + drbg->test_data->testentropy->len);
> + pr_devel("DRBG: using test entropy\n");
> + } else {
> + /* Gather entropy equal to the security strength of the DRBG.
> + * With a derivation function, a nonce is required in addition
> + * to the entropy. A nonce must be at least 1/2 of the security
> + * strength of the DRBG in size. Thus, entropy * nonce is 3/2
> + * of the strength. The consideration of a nonce is only
> + * applicable during initial seeding. */
> + entropylen = drbg_sec_strength(drbg->core->flags);
> + if (!entropylen)
> + return -EFAULT;
> + if (!reseed)
> + /* make sure we round up strength/2 in
> + * case it is not divisible by 2 */
> + entropylen = ((entropylen + 1) / 2) * 3;
> + pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
> + entropylen);
> + entropy = kzalloc(entropylen, GFP_KERNEL);
> + if (!entropy)
> + return -ENOMEM;
> + get_random_bytes(entropy, entropylen);
> + drbg_string_fill(&data1, entropy, entropylen);
> + }
> +
> + /* concatenation of entropy with personalization str / addtl input)
> + * the variable pers is directly handed by the caller, check its
> + * contents whether it is appropriate */
> + if (pers && pers->buf && 0 < pers->len && NULL == pers->next) {
> + data1.next = pers;
> + pr_devel("DRBG: using personalization string\n");
> + }
> +
> + ret = drbg->d_ops->update(drbg, &data1, reseed);
> + if (ret)
> + goto out;
> +
> + drbg->seeded = true;
> + /* 10.1.1.2 / 10.1.1.3 step 5 */
> + drbg->reseed_ctr = 1;
> +
> +out:
> + if (entropy)
> + kzfree(entropy);
> + return ret;
> +}
> +
> +/*
> + * Free all substructures in a DRBG state without the DRBG state structure
> + */
> +static inline void drbg_dealloc_state(struct drbg_state *drbg)
> +{
> + if (!drbg)
> + return;
> + if (drbg->V)
> + kzfree(drbg->V);
> + drbg->V = NULL;
> + if (drbg->C)
> + kzfree(drbg->C);
> + drbg->C = NULL;
> + if (drbg->scratchpad)
> + kzfree(drbg->scratchpad);
> + drbg->scratchpad = NULL;
> + drbg->reseed_ctr = 0;
> +#ifdef CONFIG_CRYPTO_FIPS
> + if (drbg->prev)
> + kzfree(drbg->prev);
> + drbg->prev = NULL;
> + drbg->fips_primed = false;
> +#endif
> +}
> +
> +/*
> + * Allocate all sub-structures for a DRBG state
> + * The DRBG state structure must already be allocated
> + */
> +static inline int drbg_alloc_state(struct drbg_state *drbg)
> +{
> + int ret = -ENOMEM;
> + unsigned int sb_size = 0;
> +
> + if (!drbg)
> + return -EINVAL;
> +
> + drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
> + if (!drbg->V)
> + goto err;
> + drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
> + if (!drbg->C)
> + goto err;
> +#ifdef CONFIG_CRYPTO_FIPS
> + drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
> + if (!drbg->prev)
> + goto err;
> + drbg->fips_primed = false;
> +#endif
> + /* scratchpad is only generated for CTR and Hash */
> + if (drbg->core->flags & DRBG_HMAC)
> + sb_size = 0;
> + else if (drbg->core->flags & DRBG_CTR)
> + sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
> + drbg_statelen(drbg) + /* df_data */
> + drbg_blocklen(drbg) + /* pad */
> + drbg_blocklen(drbg) + /* iv */
> + drbg_statelen(drbg); /* temp */
> + else
> + sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
> +
> + if (0 < sb_size) {
> + drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
> + if (!drbg->scratchpad)
> + goto err;
> + }
> + spin_lock_init(&drbg->drbg_lock);
> + return 0;
> +
> +err:
> + drbg_dealloc_state(drbg);
> + return ret;
> +}
> +
> +/*
> + * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
> + * and perform all operations on this shadow copy. After finishing, restore
> + * the updated state of the shadow copy into original drbg state. This way,
> + * only the read and write operations of the original drbg state must be
> + * locked
> + */
> +
> +/*
> + * Copy the DRBG state
> + */
> +static inline void drbg_copy_drbg(struct drbg_state *src,
> + struct drbg_state *dst)
> +{
> + if (!src || !dst)
> + return;
> + memcpy(dst->V, src->V, drbg_statelen(src));
> + memcpy(dst->C, src->C, drbg_statelen(src));
> + dst->reseed_ctr = src->reseed_ctr;
> + /* no copy of scratchpad */
> + /* priv_data is initialized with call to crypto_init */
> + /* d_ops and core are set outside, as these parameters are const */
> + dst->seeded = src->seeded;
> + dst->pr = src->pr;
> +#ifdef CONFIG_CRYPTO_FIPS
> + dst->fips_primed = src->fips_primed;
> + memcpy(dst->prev, src->prev, drbg_blocklen(src));
> +#endif
> + /* test_data is set outside to prevent it being copied back */
> +}
> +/*
> + * Generate shadow copy of the DRBG state
> + */
> +static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
> +{
> + int ret = -ENOMEM;
> + struct drbg_state *tmp = NULL;
> +
> + /* some sanity checks */
> + if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
> + pr_devel("DRBG: attempt to generate shadow copy for "
> + "uninitialized DRBG state rejected\n");
> + return -EINVAL;
> + }
> + /* HMAC does not have a scratchpad */
> + if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
> + return -EINVAL;
> +
> + tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
> + if (!tmp)
> + return -ENOMEM;
> +
> + /* read-only data as they are defined as const, no lock needed */
> + tmp->core = drbg->core;
> + tmp->d_ops = drbg->d_ops;
> +
> + ret = drbg_alloc_state(tmp);
> + if (ret)
> + goto err;
> +
> + spin_lock_bh(&drbg->drbg_lock);
> + drbg_copy_drbg(drbg, tmp);
> + /* only make a link to the test buffer, as we only read that data */
> + tmp->test_data = drbg->test_data;
> + spin_unlock_bh(&drbg->drbg_lock);
> + *shadow = tmp;
> + return 0;
> +
> +err:
> + if (tmp)
> + kzfree(tmp);
> + return ret;
> +}
> +
> +/*
> + * Restore shadow state into original DRBG state
> + */
> +static void drbg_restore_shadow(struct drbg_state *drbg,
> + struct drbg_state **shadow)
> +{
> + struct drbg_state *tmp = *shadow;
> +
> + spin_lock_bh(&drbg->drbg_lock);
> + drbg_copy_drbg(tmp, drbg);
> + spin_unlock_bh(&drbg->drbg_lock);
> + drbg_dealloc_state(tmp);
> + kzfree(tmp);
> + *shadow = NULL;
> +}
> +
> +/*************************************************************************
> + * DRBG interface functions
> + *************************************************************************/
> +
> +/*
> + * DRBG generate function as required by SP800-90A - this function
> + * generates random numbers
> + *
> + * @drbg DRBG state handle
> + * @buf Buffer where to store the random numbers -- the buffer must already
> + * be pre-allocated by caller
> + * @buflen Length of output buffer - this value defines the number of random
> + * bytes pulled from DRBG
> + * @addtl Additional input that is mixed into state, may be NULL -- note
> + * the entropy is pulled by the DRBG internally unconditionally
> + * as defined in SP800-90A. The additional input is mixed into
> + * the state in addition to the pulled entropy.
> + *
> + * return: generated number of bytes
> + */
> +static int drbg_generate(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + int len = 0;
> + struct drbg_state *shadow = NULL;
> +
> + if (0 == buflen || !buf) {
> + pr_devel("DRBG: no output buffer provided\n");
> + return -EINVAL;
> + }
> + if (addtl && NULL == addtl->buf && 0 < addtl->len) {
> + pr_devel("DRBG: wrong format of additional information\n");
> + return -EINVAL;
> + }
> +
> + len = drbg_make_shadow(drbg, &shadow);
> + if (len) {
> + pr_devel("DRBG: shadow copy cannot be generated\n");
> + return len;
> + }
> + /* 9.3.1 step 2 */
> + len = -EINVAL;
> + if (buflen > (drbg_max_request_bytes(shadow))) {
> + pr_devel("DRBG: requested random numbers too large %u\n",
> + buflen);
> + goto err;
> + }
> + /* 9.3.1 step 3 is implicit with the chosen DRBG */
> + /* 9.3.1 step 4 */
> + if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
> + pr_devel("DRBG: additional information string too long %zu\n",
> + addtl->len);
> + goto err;
> + }
> + /* 9.3.1 step 5 is implicit with the chosen DRBG */
> + /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
> + * bit convoluted here, we make it simpler */
> + if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
> + shadow->seeded = false;
> +
> + /* allocate cipher handle */
> + if (shadow->d_ops->crypto_init) {
> + len = shadow->d_ops->crypto_init(shadow);
> + if (len)
> + goto err;
> + }
> +
> + if (shadow->pr || !shadow->seeded) {
> + pr_devel("DRBG: reseeding before generation (prediction "
> + "resistance: %s, state %s)\n",
> + drbg->pr ? "true" : "false",
> + drbg->seeded ? "seeded" : "unseeded");
> + /* 9.3.1 steps 7.1 through 7.3 */
> + len = drbg_seed(shadow, addtl, true);
> + if (len)
> + goto err;
> + /* 9.3.1 step 7.4 */
> + addtl = NULL;
> + }
> + /* 9.3.1 step 8 and 10 */
> + len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
> +
> + /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
> + shadow->reseed_ctr++;
> + if (0 >= len)
> + goto err;
> +
> + /* 11.3.3 -- re-perform self tests after some generated random
> + * numbers, the chosen value after which self test is performed
> + * is arbitrary, but it should be reasonable */
> + /* Here we do not perform the self tests because of the following
> + * reasons: it is mathematically impossible that the initial self tests
> + * were successfully and the following are not. If the initial would
> + * pass and the following would not, the kernel integrity is violated.
> + * In this case, the entire kernel operation is questionable and it
> + * is unlikely that the integrity violation only affects to the
> + * correct operation of the DRBG.
> + */
> +#if 0
> + if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
> + int err = 0;
> + pr_devel("DRBG: start to perform self test\n");
> + if (drbg->core->flags & DRBG_HMAC)
> + err = alg_test("drbg(pr(hmac(sha256)))",
> + "drbg(pr(hmac(sha256)))", 0, 0);
> + else if (drbg->core->flags & DRBG_CTR)
> + err = alg_test("drbg(pr(ctr(aes128)))",
> + "drbg(pr(ctr(aes128)))", 0, 0);
> + else
> + err = alg_test("drbg(pr(sha256))",
> + "drbg(pr(sha256))", 0, 0);
> + if (err) {
> + pr_err("DRBG: periodical self test failed\n");
> + /* uninstantiate implies that from now on, only errors
> + * are returned when reusing this DRBG cipher handle */
> + drbg_uninstantiate(drbg);
> + drbg_dealloc_state(shadow);
> + kzfree(shadow);
> + return 0;
> + } else {
> + pr_devel("DRBG: self test successful\n");
> + }
> + }
> +#endif
> +
> +err:
> + if (shadow->d_ops->crypto_fini)
> + shadow->d_ops->crypto_fini(shadow);
> + drbg_restore_shadow(drbg, &shadow);
> + return len;
> +}
> +
> +/*
> + * Wrapper around drbg_generate which can pull arbitrary long strings
> + * from the DRBG without hitting the maximum request limitation.
> + *
> + * Parameters: see drbg_generate
> + * Return codes: see drbg_generate -- if one drbg_generate request fails,
> + * the entire drbg_generate_long request fails
> + */
> +static int drbg_generate_long(struct drbg_state *drbg,
> + unsigned char *buf, unsigned int buflen,
> + struct drbg_string *addtl)
> +{
> + int len = 0;
> + unsigned int slice = 0;
> + do {
> + int tmplen = 0;
> + unsigned int chunk = 0;
> + slice = ((buflen - len) / drbg_max_request_bytes(drbg));
> + chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
> + tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
> + if (0 >= tmplen)
> + return tmplen;
> + len += tmplen;
> + } while (slice > 0);
> + return len;
> +}
> +
> +/*
> + * DRBG instantiation function as required by SP800-90A - this function
> + * sets up the DRBG handle, performs the initial seeding and all sanity
> + * checks required by SP800-90A
> + *
> + * @drbg memory of state -- if NULL, new memory is allocated
> + * @pers Personalization string that is mixed into state, may be NULL -- note
> + * the entropy is pulled by the DRBG internally unconditionally
> + * as defined in SP800-90A. The additional input is mixed into
> + * the state in addition to the pulled entropy.
> + * @coreref reference to core
> + * @pr prediction resistance enabled
> + *
> + * return
> + * 0 on success
> + * error value otherwise
> + */
> +static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
> + int coreref, bool pr)
> +{
> + int ret = -ENOMEM;
> +
> + pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
> + "%s\n", coreref, pr ? "enabled" : "disabled");
> + drbg->core = &drbg_cores[coreref];
> + drbg->pr = pr;
> + drbg->seeded = false;
> + switch (drbg->core->flags & DRBG_TYPE_MASK) {
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> + case DRBG_HMAC:
> + drbg->d_ops = &drbg_hmac_ops;
> + break;
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> + case DRBG_HASH:
> + drbg->d_ops = &drbg_hash_ops;
> + break;
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> + case DRBG_CTR:
> + drbg->d_ops = &drbg_ctr_ops;
> + break;
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + /* 9.1 step 1 is implicit with the selected DRBG type -- see
> + * drbg_sec_strength() */
> +
> + /* 9.1 step 2 is implicit as caller can select prediction resistance
> + * and the flag is copied into drbg->flags --
> + * all DRBG types support prediction resistance */
> +
> + /* 9.1 step 4 is implicit in drbg_sec_strength */
> +
> + /* no allocation of drbg as this is done by the kernel crypto API */
> + ret = drbg_alloc_state(drbg);
> + if (ret)
> + return ret;
> +
> + ret = -EFAULT;
> + /* allocate cipher handle */
> + if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
> + goto err;
> + /* 9.1 step 6 through 11 */
> + ret = drbg_seed(drbg, pers, false);
> + /* deallocate cipher handle */
> + if (drbg->d_ops->crypto_fini)
> + drbg->d_ops->crypto_fini(drbg);
> + if (ret)
> + goto err;
> +
> + return 0;
> +
> +err:
> + drbg_dealloc_state(drbg);
> + return ret;
> +}
> +
> +/*
> + * DRBG uninstantiate function as required by SP800-90A - this function
> + * frees all buffers and the DRBG handle
> + *
> + * @drbg DRBG state handle
> + *
> + * return
> + * 0 on success
> + */
> +static int drbg_uninstantiate(struct drbg_state *drbg)
> +{
> + spin_lock_bh(&drbg->drbg_lock);
> + drbg_dealloc_state(drbg);
> + /* no scrubbing of test_data -- this shall survive an uninstantiate */
> + spin_unlock_bh(&drbg->drbg_lock);
> + /* no freeing of drbg as this is done by the kernel crypto API */
> + return 0;
> +}
> +
> +/*
> + * Helper function for setting the test data in the DRBG
> + *
> + * @drbg DRBG state handle
> + * @test_data test data to sets
> + */
> +static inline void drbg_set_testdata(struct drbg_state *drbg,
> + struct drbg_test_data *test_data)
> +{
> + if (!test_data || !test_data->testentropy)
> + return;
> + spin_lock_bh(&drbg->drbg_lock);
> + drbg->test_data = test_data;
> + spin_unlock_bh(&drbg->drbg_lock);
> +}
> +
> +/***************************************************************
> + * Kernel crypto APi cipher invocations requested by DRBG
> + ***************************************************************/
> +
> +#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
> +struct sdesc {
> + struct shash_desc shash;
> + char ctx[];
> +};
> +
> +static int drbg_init_hash_kernel(struct drbg_state *drbg)
> +{
> + struct sdesc *sdesc;
> + struct crypto_shash *tfm;
> +
> + tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
> + if (IS_ERR(tfm)) {
> + pr_info("DRBG: could not allocate digest TFM handle\n");
> + return PTR_ERR(tfm);
> + }
> + BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
> + sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
> + GFP_KERNEL);
> + if (!sdesc) {
> + crypto_free_shash(tfm);
> + return -ENOMEM;
> + }
> +
> + sdesc->shash.tfm = tfm;
> + sdesc->shash.flags = 0;
> + drbg->priv_data = sdesc;
> + return 0;
> +}
> +
> +static int drbg_fini_hash_kernel(struct drbg_state *drbg)
> +{
> + struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
> + if (sdesc) {
> + crypto_free_shash(sdesc->shash.tfm);
> + kzfree(sdesc);
> + }
> + drbg->priv_data = NULL;
> + return 0;
> +}
> +
> +static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
> + unsigned char *outval, const struct drbg_string *in)
> +{
> + struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
> +
> + if (key)
> + crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
> + crypto_shash_init(&sdesc->shash);
> + for (; NULL != in; in = in->next)
> + crypto_shash_update(&sdesc->shash, in->buf, in->len);
> + return crypto_shash_final(&sdesc->shash, outval);
> +}
> +#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
> +
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static int drbg_init_sym_kernel(struct drbg_state *drbg)
> +{
> + int ret = 0;
> + struct crypto_blkcipher *tfm;
> +
> + tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
> + if (IS_ERR(tfm)) {
> + pr_info("DRBG: could not allocate cipher TFM handle\n");
> + return PTR_ERR(tfm);
> + }
> + BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
> + drbg->priv_data = tfm;
> + return ret;
> +}
> +
> +static int drbg_fini_sym_kernel(struct drbg_state *drbg)
> +{
> + struct crypto_blkcipher *tfm =
> + (struct crypto_blkcipher *)drbg->priv_data;
> + if (tfm)
> + crypto_free_blkcipher(tfm);
> + drbg->priv_data = NULL;
> + return 0;
> +}
> +
> +static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
> + unsigned char *outval, const struct drbg_string *in)
> +{
> + int ret = 0;
> + struct scatterlist sg_in, sg_out;
> + struct blkcipher_desc desc;
> + struct crypto_blkcipher *tfm =
> + (struct crypto_blkcipher *)drbg->priv_data;
> +
> + desc.tfm = tfm;
> + desc.flags = 0;
> + crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
> + /* in is only component */
> + sg_init_one(&sg_in, in->buf, in->len);
> + sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
> + ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
> +
> + return ret;
> +}
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +
> +/***************************************************************
> + * Kernel crypto API interface to register DRBG
> + ***************************************************************/
> +
> +/*
> + * Look up the DRBG flags by given kernel crypto API cra_name
> + * The code uses the drbg_cores definition to do this
> + *
> + * @cra_name kernel crypto API cra_name
> + * @coreref reference to integer which is filled with the pointer to
> + * the applicable core
> + * @pr reference for setting prediction resistance
> + *
> + * return: flags
> + */
> +static inline void drbg_convert_tfm_core(const char *cra_name,
> + int *coreref, bool *pr)
> +{
> + int i = 0;
> + size_t start = 0;
> + int len = 0;
> +
> + *pr = true;
> + /* disassemble the names */
> + if (0 == memcmp(cra_name, "drbg(nopr(", 10)) {
> + start = 10;
> + *pr = false;
> + } else if (0 == memcmp(cra_name, "drbg(pr(", 8)) {
> + start = 8;
> + } else {
> + return;
> + }
> +
> + /* remove the first part and the closing parenthesis */
> + len = strlen(cra_name) - start - 2;
> + for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
> + if (0 == memcmp(cra_name + start,
> + drbg_cores[i].cra_name, len)) {
> + *coreref = i;
> + return;
> + }
> + }
> +}
> +
> +/*
> + * Initialize one DRBG invoked by the kernel crypto API
> + *
> + * Function uses the kernel crypto API cra_name to look up
> + * the flags to instantiate the DRBG
> + */
> +static int drbg_kcapi_init(struct crypto_tfm *tfm)
> +{
> + struct drbg_state *drbg = crypto_tfm_ctx(tfm);
> + bool pr = false;
> + int coreref = 0;
> +
> + drbg_convert_tfm_core(crypto_tfm_alg_name(tfm), &coreref, &pr);
> + /* when personalization string is needed, the caller must call reset
> + * and provide the personalization string as seed information */
> + return drbg_instantiate(drbg, NULL, coreref, pr);
> +}
> +
> +static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
> +{
> + drbg_uninstantiate(crypto_tfm_ctx(tfm));
> +}
> +
> +/*
> + * Generate random numbers invoked by the kernel crypto API:
> + * The API of the kernel crypto API is extended as follows:
> + *
> + * If dlen is larger than zero, rdata is interpreted as the output buffer
> + * where random data is to be stored.
> + *
> + * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
> + * which holds the additional information string that is used for the
> + * DRBG generation process. The output buffer that is to be used to store
> + * data is also pointed to by struct drbg_gen.
> + *
> + */
> +static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
> + unsigned int dlen)
> +{
> + struct drbg_state *drbg = crypto_rng_ctx(tfm);
> + if (0 < dlen) {
> + return drbg_generate_long(drbg, rdata, dlen, NULL);
> + } else {
> + struct drbg_gen *data = (struct drbg_gen *)rdata;
> + /* catch NULL pointer */
> + if (!data)
> + return 0;
> + drbg_set_testdata(drbg, data->test_data);
> + return drbg_generate_long(drbg, data->outbuf, data->outlen,
> + data->addtl);
> + }
> +}
> +
> +/*
> + * Reset the DRBG invoked by the kernel crypto API
> + * The reset implies a full re-initialization of the DRBG. Similar to the
> + * generate function of drbg_kcapi_random, this function extends the
> + * kernel crypto API interface with struct drbg_gen
> + */
> +static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
> +{
> + struct drbg_state *drbg = crypto_rng_ctx(tfm);
> + struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
> + bool pr = false;
> + struct drbg_string seed_string;
> + int coreref = 0;
> +
> + drbg_uninstantiate(drbg);
> + drbg_convert_tfm_core(crypto_tfm_alg_name(tfm_base), &coreref, &pr);
> + if (0 < slen) {
> + drbg_string_fill(&seed_string, seed, slen);
> + return drbg_instantiate(drbg, &seed_string, coreref, pr);
> + } else {
> + struct drbg_gen *data = (struct drbg_gen *)seed;
> + /* allow invocation of API call with NULL, 0 */
> + if (!data)
> + return drbg_instantiate(drbg, NULL, coreref, pr);
> + drbg_set_testdata(drbg, data->test_data);
> + return drbg_instantiate(drbg, data->addtl, coreref, pr);
> + }
> +}
> +
> +/***************************************************************
> + * Kernel module: code to load the module
> + ***************************************************************/
> +
> +/*
> + * Tests as defined in 11.3.2 in addition to the cipher tests: testing
> + * of the error handling.
> + *
> + * Note, testing of failing seed source as defined in 11.3.2 is not applicable
> + * as seed source of get_random_bytes does not fail.
> + * Note, testing the reseed counter is not done as an automatic reseeding
> + * is performed in drbg_generate when the reseed counter is too large.
> + */
> +static inline int __init drbg_healthcheck_sanity(void)
> +{
> +#ifdef CONFIG_CRYPTO_FIPS
> + unsigned int len = 0;
> +#define OUTBUFLEN 16
> + unsigned char buf[OUTBUFLEN];
> + struct drbg_state *drbg = NULL;
> + int ret = -EFAULT;
> + int rc = -EFAULT;
> + bool pr = false;
> + int coreref = 0;
> + struct drbg_string addtl;
> + size_t max_addtllen, max_request_bytes;
> +
> + /* only perform test in FIPS mode */
> + if (0 == fips_enabled)
> + return 0;
> +
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> + drbg_convert_tfm_core("drbg(nopr(ctr(aes128)))", &coreref, &pr);
> +#elif CONFIG_CRYPTO_DRBG_HASH
> + drbg_convert_tfm_core("drbg(nopr(sha256)", &coreref, &pr);
> +#else
> + drbg_convert_tfm_core("drbg(nopr(hmac(sha256)))", &coreref, &pr);
> +#endif
> +
> + drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
> + if (!drbg)
> + return -ENOMEM;
> +
> + /* if the following tests fail, it is likely that there is a buffer
> + * overflow as buf is much smaller than the requested or provided
> + * string lengths -- in case the error handling does not succeed
> + * we may get an OOPS. And we want to get an OOPS as this is a
> + * grave bug */
> +
> + /* get a valid instance of DRBG for following tests */
> + ret = drbg_instantiate(drbg, NULL, coreref, pr);
> + if (ret) {
> + rc = ret;
> + goto outbuf;
> + }
> + max_addtllen = drbg_max_addtl(drbg);
> + max_request_bytes = drbg_max_request_bytes(drbg);
> + drbg_string_fill(&addtl, buf, max_addtllen + 1);
> + /* overflow addtllen with additonal info string */
> + len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
> + BUG_ON(0 < len);
> + /* overflow max_bits */
> + len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
> + BUG_ON(0 < len);
> + drbg_uninstantiate(drbg);
> +
> + /* overflow max addtllen with personalization string */
> + ret = drbg_instantiate(drbg, &addtl, coreref, pr);
> + BUG_ON(0 == ret);
> + /* test uninstantated DRBG */
> + len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
> + BUG_ON(0 < len);
> + /* all tests passed */
> + rc = 0;
> +
> + pr_devel("DRBG: Sanity tests for failure code paths successfully "
> + "completed\n");
> +
> + drbg_uninstantiate(drbg);
> +outbuf:
> + kzfree(drbg);
> + return rc;
> +#else /* CONFIG_CRYPTO_FIPS */
> + return 0;
> +#endif /* CONFIG_CRYPTO_FIPS */
> +}
> +
> +
> +static struct crypto_alg drbg_algs[22];
> +
> +/*
> + * Fill the array drbg_algs used to register the different DRBGs
> + * with the kernel crypto API. To fill the array, the information
> + * from drbg_cores[] is used.
> + */
> +static inline void __init drbg_fill_array(unsigned long i, unsigned long j,
> + int pr)
> +{
> + int pos = 0;
> +
> + memset(&drbg_algs[i], 0, sizeof(struct crypto_alg));
> + if (pr) {
> + memcpy(drbg_algs[i].cra_name, "drbg(pr(", 8);
> + memcpy(drbg_algs[i].cra_driver_name, "drbg_pr_", 8);
> + pos = 8;
> + } else {
> + memcpy(drbg_algs[i].cra_name, "drbg(nopr(", 10);
> + memcpy(drbg_algs[i].cra_driver_name, "drbg_nopr_", 10);
> + pos = 10;
> + }
> + memcpy(drbg_algs[i].cra_name + pos, drbg_cores[j].cra_name,
> + strlen(drbg_cores[j].cra_name));
> + memcpy(drbg_algs[i].cra_name + pos + strlen(drbg_cores[j].cra_name),
> + "))", 2);
> + memcpy(drbg_algs[i].cra_driver_name + pos,
> + drbg_cores[j].cra_driver_name,
> + strlen(drbg_cores[j].cra_driver_name));
> + drbg_algs[i].cra_priority = 100;
> + drbg_algs[i].cra_flags = CRYPTO_ALG_TYPE_RNG;
> + drbg_algs[i].cra_ctxsize = sizeof(struct drbg_state);
> + drbg_algs[i].cra_type = &crypto_rng_type;
> + drbg_algs[i].cra_module = THIS_MODULE;
> + drbg_algs[i].cra_init = drbg_kcapi_init;
> + drbg_algs[i].cra_exit = drbg_kcapi_cleanup;
> + drbg_algs[i].cra_u.rng.rng_make_random = drbg_kcapi_random;
> + drbg_algs[i].cra_u.rng.rng_reset = drbg_kcapi_reset;
> + drbg_algs[i].cra_u.rng.seedsize = 0;
> +}
> +
> +static int __init drbg_init(void)
> +{
> + unsigned int i = 0; /* pointer to drbg_algs */
> + unsigned int j = 0; /* pointer to drbg_cores */
> + int ret = -EFAULT;
> +
> + ret = drbg_healthcheck_sanity();
> + if (ret)
> + return ret;
> +
> + if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
> + pr_info("DRBG: Cannot register all DRBG types"
> + "(slots needed: %lu, slots available: %lu)\n",
> + ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
> + return ret;
> + }
> +
> + /* each DRBG definition can be used with PR and without PR, thus
> + * we instantiate each DRBG in drbg_cores[] twice */
> + for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++) {
> + drbg_fill_array(i, j, 1);
> + i++;
> + drbg_fill_array(i, j, 0);
> + i++;
> + }
> + return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
> +}
> +
> +void __exit drbg_exit(void)
> +{
> + crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
> +}
> +
> +module_init(drbg_init);
> +module_exit(drbg_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Stephan Mueller <[email protected]>");
> +MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) using following cores:"
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +"HMAC "
> +#endif
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> +"Hash "
> +#endif
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +"CTR"
> +#endif
> +);
>