summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig106
-rw-r--r--crypto/Makefile2
-rw-r--r--crypto/ahash.c12
-rw-r--r--crypto/algapi.c14
-rw-r--r--crypto/algif_skcipher.c2
-rw-r--r--crypto/asymmetric_keys/public_key.c1
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c49
-rw-r--r--crypto/async_tx/async_xor.c3
-rw-r--r--crypto/cryptd.c12
-rw-r--r--crypto/des_generic.c22
-rw-r--r--crypto/drbg.c1991
-rw-r--r--crypto/eseqiv.c8
-rw-r--r--crypto/gcm.c30
-rw-r--r--crypto/lz4.c2
-rw-r--r--crypto/lz4hc.c2
-rw-r--r--crypto/lzo.c8
-rw-r--r--crypto/mcryptd.c705
-rw-r--r--crypto/seqiv.c16
-rw-r--r--crypto/sha256_generic.c3
-rw-r--r--crypto/sha512_generic.c3
-rw-r--r--crypto/tcrypt.c114
-rw-r--r--crypto/testmgr.c1218
-rw-r--r--crypto/testmgr.h1224
-rw-r--r--crypto/zlib.c8
24 files changed, 4831 insertions, 724 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ce4012a58781..87bbc9c1e681 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -23,7 +23,8 @@ 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 || CRYPTO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
+ depends on MODULE_SIG
help
This options enables the fips boot option which is
required if you want to system to operate in a FIPS 200
@@ -157,6 +158,20 @@ config CRYPTO_CRYPTD
converts an arbitrary synchronous software crypto algorithm
into an asynchronous algorithm that executes in a kernel thread.
+config CRYPTO_MCRYPTD
+ tristate "Software async multi-buffer crypto daemon"
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_HASH
+ select CRYPTO_MANAGER
+ select CRYPTO_WORKQUEUE
+ help
+ This is a generic software asynchronous crypto daemon that
+ provides the kernel thread to assist multi-buffer crypto
+ algorithms for submitting jobs and flushing jobs in multi-buffer
+ crypto algorithms. Multi-buffer crypto algorithms are executed
+ in the context of this kernel thread and drivers can post
+ their crypto request asynchronously to be processed by this daemon.
+
config CRYPTO_AUTHENC
tristate "Authenc support"
select CRYPTO_AEAD
@@ -540,6 +555,17 @@ config CRYPTO_SHA1_ARM
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
using optimized ARM assembler.
+config CRYPTO_SHA1_ARM_NEON
+ tristate "SHA1 digest algorithm (ARM NEON)"
+ depends on ARM && KERNEL_MODE_NEON
+ select CRYPTO_SHA1_ARM
+ select CRYPTO_SHA1
+ select CRYPTO_HASH
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+ using optimized ARM NEON assembly, when NEON instructions are
+ available.
+
config CRYPTO_SHA1_PPC
tristate "SHA1 digest algorithm (powerpc)"
depends on PPC
@@ -547,6 +573,22 @@ config CRYPTO_SHA1_PPC
This is the powerpc hardware accelerated implementation of the
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+config CRYPTO_SHA1_MB
+ tristate "SHA1 digest algorithm (x86_64 Multi-Buffer, Experimental)"
+ depends on X86 && 64BIT
+ select CRYPTO_SHA1
+ select CRYPTO_HASH
+ select CRYPTO_MCRYPTD
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+ using multi-buffer technique. This algorithm computes on
+ multiple data lanes concurrently with SIMD instructions for
+ better throughput. It should not be enabled by default but
+ used when there is significant amount of work to keep the keep
+ the data lanes filled to get performance benefit. If the data
+ lanes remain unfilled, a flush operation will be initiated to
+ process the crypto jobs, adding a slight latency.
+
config CRYPTO_SHA256
tristate "SHA224 and SHA256 digest algorithm"
select CRYPTO_HASH
@@ -589,6 +631,21 @@ config CRYPTO_SHA512_SPARC64
SHA-512 secure hash standard (DFIPS 180-2) implemented
using sparc64 crypto instructions, when available.
+config CRYPTO_SHA512_ARM_NEON
+ tristate "SHA384 and SHA512 digest algorithm (ARM NEON)"
+ depends on ARM && KERNEL_MODE_NEON
+ select CRYPTO_SHA512
+ select CRYPTO_HASH
+ help
+ SHA-512 secure hash standard (DFIPS 180-2) implemented
+ using ARM NEON instructions, when available.
+
+ This version of SHA implements a 512 bit hash with 256 bits of
+ security against collision attacks.
+
+ This code also includes SHA-384, a 384 bit hash with 192 bits
+ of security against collision attacks.
+
config CRYPTO_TGR192
tristate "Tiger digest algorithms"
select CRYPTO_HASH
@@ -1019,6 +1076,19 @@ config CRYPTO_DES_SPARC64
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3),
optimized using SPARC64 crypto opcodes.
+config CRYPTO_DES3_EDE_X86_64
+ tristate "Triple DES EDE cipher algorithm (x86-64)"
+ depends on X86 && 64BIT
+ select CRYPTO_ALGAPI
+ select CRYPTO_DES
+ help
+ Triple DES EDE (FIPS 46-3) algorithm.
+
+ This module provides implementation of the Triple DES EDE cipher
+ algorithm that is optimized for x86-64 processors. Two versions of
+ algorithm are provided; regular processing one input block and
+ one that processes three blocks parallel.
+
config CRYPTO_FCRYPT
tristate "FCrypt cipher algorithm"
select CRYPTO_ALGAPI
@@ -1380,6 +1450,40 @@ config CRYPTO_ANSI_CPRNG
ANSI X9.31 A.2.4. Note that this option must be enabled if
CRYPTO_FIPS is selected
+menuconfig CRYPTO_DRBG_MENU
+ tristate "NIST SP800-90A DRBG"
+ help
+ NIST SP800-90A compliant DRBG. In the following submenu, one or
+ more of the DRBG types must be selected.
+
+if CRYPTO_DRBG_MENU
+
+config CRYPTO_DRBG_HMAC
+ bool "Enable HMAC DRBG"
+ default y
+ select CRYPTO_HMAC
+ help
+ Enable the HMAC DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_HASH
+ bool "Enable Hash DRBG"
+ select CRYPTO_HASH
+ help
+ Enable the Hash DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_CTR
+ bool "Enable CTR DRBG"
+ select CRYPTO_AES
+ help
+ Enable the CTR DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG
+ tristate
+ default CRYPTO_DRBG_MENU if (CRYPTO_DRBG_HMAC || CRYPTO_DRBG_HASH || CRYPTO_DRBG_CTR)
+ select CRYPTO_RNG
+
+endif # if CRYPTO_DRBG_MENU
+
config CRYPTO_USER_API
tristate
diff --git a/crypto/Makefile b/crypto/Makefile
index 38e64231dcd3..1445b9100c05 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o
obj-$(CONFIG_CRYPTO_CCM) += ccm.o
obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
+obj-$(CONFIG_CRYPTO_MCRYPTD) += mcryptd.o
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
@@ -92,6 +93,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_CRYPTO_DRBG) += drbg.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
diff --git a/crypto/ahash.c b/crypto/ahash.c
index f2a5d8f656ff..f6a36a52d738 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -131,8 +131,10 @@ int crypto_hash_walk_first(struct ahash_request *req,
{
walk->total = req->nbytes;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
walk->sg = req->src;
@@ -147,8 +149,10 @@ int crypto_ahash_walk_first(struct ahash_request *req,
{
walk->total = req->nbytes;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
walk->sg = req->src;
@@ -167,8 +171,10 @@ int crypto_hash_walk_first_compat(struct hash_desc *hdesc,
{
walk->total = len;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_hash_alignmask(hdesc->tfm);
walk->sg = sg;
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 7a1ae87f1683..e8d3a7dca8c4 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -41,8 +41,20 @@ static inline int crypto_set_driver_name(struct crypto_alg *alg)
return 0;
}
+static inline void crypto_check_module_sig(struct module *mod)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ if (fips_enabled && mod && !mod->sig_ok)
+ panic("Module %s signature verification failed in FIPS mode\n",
+ mod->name);
+#endif
+ return;
+}
+
static int crypto_check_alg(struct crypto_alg *alg)
{
+ crypto_check_module_sig(alg->cra_module);
+
if (alg->cra_alignmask & (alg->cra_alignmask + 1))
return -EINVAL;
@@ -430,6 +442,8 @@ int crypto_register_template(struct crypto_template *tmpl)
down_write(&crypto_alg_sem);
+ crypto_check_module_sig(tmpl->module);
+
list_for_each_entry(q, &crypto_template_list, list) {
if (q == tmpl)
goto out;
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index a19c027b29bd..83187f497c7c 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -49,7 +49,7 @@ struct skcipher_ctx {
struct ablkcipher_request req;
};
-#define MAX_SGL_ENTS ((PAGE_SIZE - sizeof(struct skcipher_sg_list)) / \
+#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
sizeof(struct scatterlist) - 1)
static inline int skcipher_sndbuf(struct sock *sk)
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 97eb001960b9..2f6e4fb1a1ea 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -121,6 +121,7 @@ static int public_key_verify_signature_2(const struct key *key,
struct asymmetric_key_subtype public_key_subtype = {
.owner = THIS_MODULE,
.name = "public_key",
+ .name_len = sizeof("public_key") - 1,
.describe = public_key_describe,
.destroy = public_key_destroy,
.verify_signature = public_key_verify_signature_2,
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 79175e6ea0b2..2421f46184ce 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -128,6 +128,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
{
struct win_certificate wrapper;
const u8 *pkcs7;
+ unsigned len;
if (ctx->sig_len < sizeof(wrapper)) {
pr_debug("Signature wrapper too short\n");
@@ -154,33 +155,49 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
return -ENOTSUPP;
}
- /* Looks like actual pkcs signature length is in wrapper->length.
- * size obtained from data dir entries lists the total size of
- * certificate table which is also aligned to octawrod boundary.
- *
- * So set signature length field appropriately.
+ /* It looks like the pkcs signature length in wrapper->length and the
+ * size obtained from the data dir entries, which lists the total size
+ * of certificate table, are both aligned to an octaword boundary, so
+ * we may have to deal with some padding.
*/
ctx->sig_len = wrapper.length;
ctx->sig_offset += sizeof(wrapper);
ctx->sig_len -= sizeof(wrapper);
- if (ctx->sig_len == 0) {
+ if (ctx->sig_len < 4) {
pr_debug("Signature data missing\n");
return -EKEYREJECTED;
}
- /* What's left should a PKCS#7 cert */
+ /* What's left should be a PKCS#7 cert */
pkcs7 = pebuf + ctx->sig_offset;
- if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) {
- if (pkcs7[1] == 0x82 &&
- pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) &&
- pkcs7[3] == ((ctx->sig_len - 4) & 0xff))
- return 0;
- if (pkcs7[1] == 0x80)
- return 0;
- if (pkcs7[1] > 0x82)
- return -EMSGSIZE;
+ if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
+ goto not_pkcs7;
+
+ switch (pkcs7[1]) {
+ case 0 ... 0x7f:
+ len = pkcs7[1] + 2;
+ goto check_len;
+ case ASN1_INDEFINITE_LENGTH:
+ return 0;
+ case 0x81:
+ len = pkcs7[2] + 3;
+ goto check_len;
+ case 0x82:
+ len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
+ goto check_len;
+ case 0x83 ... 0xff:
+ return -EMSGSIZE;
+ default:
+ goto not_pkcs7;
}
+check_len:
+ if (len <= ctx->sig_len) {
+ /* There may be padding */
+ ctx->sig_len = len;
+ return 0;
+ }
+not_pkcs7:
pr_debug("Signature data not PKCS#7\n");
return -ELIBBAD;
}
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 3c562f5a60bb..e1bce26cd4f9 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -78,8 +78,6 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
tx = dma->device_prep_dma_xor(chan, dma_dest, src_list,
xor_src_cnt, unmap->len,
dma_flags);
- src_list[0] = tmp;
-
if (unlikely(!tx))
async_tx_quiesce(&submit->depend_tx);
@@ -92,6 +90,7 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
xor_src_cnt, unmap->len,
dma_flags);
}
+ src_list[0] = tmp;
dma_set_unmap(tx, unmap);
async_tx_submit(chan, tx, submit);
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 7bdd61b867c8..e592c90abebb 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -233,7 +233,7 @@ static void cryptd_blkcipher_decrypt(struct crypto_async_request *req, int err)
}
static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
@@ -241,7 +241,7 @@ static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
@@ -414,7 +414,7 @@ static int cryptd_hash_setkey(struct crypto_ahash *parent,
}
static int cryptd_hash_enqueue(struct ahash_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -422,7 +422,7 @@ static int cryptd_hash_enqueue(struct ahash_request *req,
cryptd_get_queue(crypto_ahash_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
@@ -667,14 +667,14 @@ static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err)
}
static int cryptd_aead_enqueue(struct aead_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index f6cf63f88468..298d464ab7d2 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -859,13 +859,10 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
* property.
*
*/
-static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen)
+int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key,
+ unsigned int keylen)
{
const u32 *K = (const u32 *)key;
- struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
- u32 *expkey = dctx->expkey;
- u32 *flags = &tfm->crt_flags;
if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
!((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
@@ -880,6 +877,17 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
return 0;
}
+EXPORT_SYMBOL_GPL(__des3_ede_setkey);
+
+static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+ u32 *expkey = dctx->expkey;
+
+ return __des3_ede_setkey(expkey, flags, key, keylen);
+}
static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
@@ -945,6 +953,8 @@ static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
static struct crypto_alg des_algs[2] = { {
.cra_name = "des",
+ .cra_driver_name = "des-generic",
+ .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des_ctx),
@@ -958,6 +968,8 @@ static struct crypto_alg des_algs[2] = { {
.cia_decrypt = des_decrypt } }
}, {
.cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-generic",
+ .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des3_ede_ctx),
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 000000000000..54cfd4820abc
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,1991 @@
+/*
+ * 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 <smueller@chronox.de>, 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>
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+/*
+ * The order of the DRBG definitions here matter: every DRBG is registered
+ * as stdrng. Each DRBG receives an increasing cra_priority values the later
+ * they are defined in this array (see drbg_fill_array).
+ *
+ * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and
+ * the SHA256 / AES 256 over other ciphers. Thus, the favored
+ * DRBGs are the latest entries in this array.
+ */
+static const struct drbg_core drbg_cores[] = {
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .backend_cra_name = "sha512",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .backend_cra_name = "sha256",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ .flags = DRBG_HMAC | DRBG_STRENGTH128,
+ .statelen = 20, /* block length of cipher */
+ .blocklen_bytes = 20,
+ .cra_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .blocklen_bytes = 48,
+ .cra_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .blocklen_bytes = 64,
+ .cra_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .blocklen_bytes = 32,
+ .cra_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+};
+
+/******************************************************************
+ * 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
+ *
+ * @val value to be converted
+ * @buf buffer holding the converted integer -- caller must ensure that
+ * buffer size is at least 32 bit
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
+{
+ struct s {
+ __be32 conv;
+ };
+ struct s *conversion = (struct s *) buf;
+
+ conversion->conv = cpu_to_be32(val);
+}
+
+/*
+ * 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
+#define CRYPTO_DRBG_CTR_STRING "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 list_head *in)
+{
+ int ret = 0;
+ struct drbg_string *curr = NULL;
+ struct drbg_string data;
+ short cnt = 0;
+
+ 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 */
+ list_for_each_entry(curr, in, list) {
+ const unsigned char *pos = curr->buf;
+ size_t len = curr->len;
+ /* 10.4.3 step 4.1 */
+ while (len) {
+ /* 10.4.3 step 4.2 */
+ if (drbg_blocklen(drbg) == cnt) {
+ cnt = 0;
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ }
+ out[cnt] ^= *pos;
+ pos++;
+ cnt++;
+ len--;
+ }
+ }
+ /* 10.4.3 step 4.2 for last block */
+ if (cnt)
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+
+ return ret;
+}
+
+/*
+ * 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_satelen(drbg) + drbg_blocklen(drbg)
+ * note: temp is the buffer that the BCC function operates
+ * on. BCC operates blockwise. drbg_statelen(drbg)
+ * is sufficient when the DRBG state length is a multiple
+ * of the block size. For AES192 (and maybe other ciphers)
+ * this is not correct and the length for temp is
+ * insufficient (yes, that also means for such ciphers,
+ * the final output of all BCC rounds are truncated).
+ * Therefore, add drbg_blocklen(drbg) to cover all
+ * possibilities.
+ */
+
+/* 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 list_head *seedlist)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ LIST_HEAD(bcc_list);
+ 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;
+ struct drbg_string *seed = NULL;
+
+ 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 */
+ list_for_each_entry(seed, seedlist, list)
+ inputlen += seed->len;
+ drbg_cpu_to_be32(inputlen, &L_N[0]);
+
+ /* 10.4.2 step 3 */
+ drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (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.
+ * As the calculated padlen value only covers the number of zero
+ * bytes, this value has to be incremented by one for the 0x80 byte.
+ */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ list_add_tail(&S1.list, &bcc_list);
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ list_add_tail(&S2.list, &bcc_list);
+ list_splice_tail(seedlist, &bcc_list);
+ drbg_string_fill(&S4, pad, padlen);
+ list_add_tail(&S4.list, &bcc_list);
+
+ /* 10.4.2 step 9 */
+ while (templen < (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_cpu_to_be32(i, iv);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval is implemented in next step */
+
+ /* 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 based on
+ * 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
+ *
+ * The reseed variable has an enhanced meaning compared to the update
+ * functions of the other DRBGs as follows:
+ * 0 => initial seed from initialization
+ * 1 => reseed via drbg_seed
+ * 2 => first invocation from drbg_ctr_update when addtl is present. In
+ * this case, the df_data scratchpad is not deleted so that it is
+ * available for another calls to prevent calling the DF function
+ * again.
+ * 3 => second invocation from drbg_ctr_update. When the update function
+ * was called with addtl, the df_data memory already contains the
+ * DFed addtl information and we do not need to call DF again.
+ */
+static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
+ 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));
+ if (3 > reseed)
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (seed) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /*
+ * 10.2.1.3.2 steps 2 and 3 are already covered as the allocation
+ * zeroizes 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 */
+ 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));
+ if (2 != reseed)
+ 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 list_head *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 && !list_empty(addtl)) {
+ ret = drbg_ctr_update(drbg, addtl, 2);
+ 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 */
+ ret = drbg_ctr_update(drbg, NULL, 3);
+ 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 list_head *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
+#define CRYPTO_DRBG_HMAC_STRING "HMAC "
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, vdata;
+ LIST_HEAD(seedlist);
+ LIST_HEAD(vdatalist);
+
+ if (!reseed)
+ /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
+ memset(drbg->V, 1, drbg_statelen(drbg));
+
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&seed1.list, &seedlist);
+ /* buffer of seed2 will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ list_add_tail(&seed2.list, &seedlist);
+ /* input data of seed is allowed to be NULL at this point */
+ if (seed)
+ list_splice_tail(seed, &seedlist);
+
+ drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&vdata.list, &vdatalist);
+ 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, &seedlist);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed)
+ 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 list_head *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ LIST_HEAD(datalist);
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && !list_empty(addtl)) {
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data.list, &datalist);
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
+ 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 && !list_empty(addtl))
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ else
+ ret = drbg_hmac_update(drbg, NULL, 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
+#define CRYPTO_DRBG_HASH_STRING "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)
+ *
+ * drbg_hash_process_addtl uses the scratchpad, but fully completes
+ * before either of the functions mentioned before are invoked. Therefore,
+ * drbg_hash_process_addtl does not need to be specifically considered.
+ */
+
+/* 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 list_head *entropylist)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_cpu_to_be32((outlen * 8), &input[1]);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data, input, 5);
+ list_add(&data.list, entropylist);
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
+ 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 list_head *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+ LIST_HEAD(datalist2);
+ 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 */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ list_add_tail(&data1.list, &datalist);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist);
+ }
+ list_splice_tail(seed, &datalist);
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ list_add_tail(&data1.list, &datalist2);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist2);
+ /* 10.1.1.2 / 10.1.1.3 step 4 */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
+
+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 list_head *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+ 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 || list_empty(addtl))
+ return 0;
+
+ /* 10.1.1.4 step 2a */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data1.list, &datalist);
+ list_add_tail(&data2.list, &datalist);
+ list_splice_tail(addtl, &datalist);
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+ 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;
+ LIST_HEAD(datalist);
+ unsigned char prefix = DRBG_PREFIX1;
+
+ 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));
+ list_add_tail(&data.list, &datalist);
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
+ 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 list_head *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ union {
+ unsigned char req[8];
+ __be64 req_int;
+ } u;
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl(drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 */
+ 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);
+ list_add_tail(&data1.list, &datalist);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist);
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+ 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));
+ u.req_int = cpu_to_be64(drbg->reseed_ctr);
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), u.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;
+ LIST_HEAD(seedlist);
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %zu\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)
+ 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);
+ }
+ list_add_tail(&data1.list, &seedlist);
+
+ /*
+ * concatenation of entropy with personalization str / addtl input)
+ * the variable pers is directly handed in by the caller, so check its
+ * contents whether it is appropriate
+ */
+ if (pers && pers->buf && 0 < pers->len) {
+ list_add_tail(&pers->list, &seedlist);
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ if (!reseed) {
+ memset(drbg->V, 0, drbg_statelen(drbg));
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ }
+
+ ret = drbg->d_ops->update(drbg, &seedlist, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ 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;
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ 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;
+
+ drbg->V = kmalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kmalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kmalloc(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) + drbg_blocklen(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
+ */
+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;
+ 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
+ /*
+ * Not copied:
+ * scratchpad is initialized drbg_alloc_state;
+ * priv_data is initialized with call to crypto_init;
+ * d_ops and core are set outside, as these parameters are const;
+ * test_data is set outside to prevent it being copied back.
+ */
+}
+
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ 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:
+ kzfree(tmp);
+ return ret;
+}
+
+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;
+ LIST_HEAD(addtllist);
+ struct drbg_string timestamp;
+ union {
+ cycles_t cycles;
+ unsigned char char_cycles[sizeof(cycles_t)];
+ } now;
+
+ 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 is implemented
+ * here. 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 */
+ 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;
+ }
+
+ /*
+ * Mix the time stamp into the DRBG state if the DRBG is not in
+ * test mode. If there are two callers invoking the DRBG at the same
+ * time, i.e. before the first caller merges its shadow state back,
+ * both callers would obtain the same random number stream without
+ * changing the state here.
+ */
+ if (!drbg->test_data) {
+ now.cycles = random_get_entropy();
+ drbg_string_fill(&timestamp, now.char_cycles, sizeof(cycles_t));
+ list_add_tail(&timestamp.list, &addtllist);
+ }
+ if (addtl && 0 < addtl->len)
+ list_add_tail(&addtl->list, &addtllist);
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, &addtllist);
+
+ /* 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;
+
+ /*
+ * Section 11.3.3 requires to 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.
+ * However, 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 the
+ * correct operation of the DRBG.
+ *
+ * Albeit the following code is commented out, it is provided in
+ * case somebody has a need to implement the test of 11.3.3.
+ */
+#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:
+ 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 && (len < buflen));
+ 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 */
+
+ /*
+ * 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 */
+
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ if (drbg->d_ops->crypto_init(drbg))
+ goto err;
+ ret = drbg_seed(drbg, pers, false);
+ 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);
+ 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 list_head *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ struct drbg_string *input = NULL;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ list_for_each_entry(input, in, list)
+ crypto_shash_update(&sdesc->shash, input->buf, input->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)));
+ /* there is only component in *in */
+ 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_driver_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part */
+ len = strlen(cra_driver_name) - start;
+ for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
+ if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
+ len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+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_driver_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;
+ struct drbg_string addtl;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ /* linked list variable is now local to allow modification */
+ drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ &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_driver_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);
+ /* linked list variable is now local to allow modification */
+ drbg_string_fill(&seed_string, data->addtl->buf,
+ data->addtl->len);
+ return drbg_instantiate(drbg, &seed_string, 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 2: There is no sensible way of testing the reseed counter
+ * enforcement, so skip it.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ 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 (!fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
+#elif defined 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);
+ /* 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(struct crypto_alg *alg,
+ const struct drbg_core *core, int pr)
+{
+ int pos = 0;
+ static int priority = 100;
+
+ memset(alg, 0, sizeof(struct crypto_alg));
+ memcpy(alg->cra_name, "stdrng", 6);
+ if (pr) {
+ memcpy(alg->cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(alg->cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(alg->cra_driver_name + pos, core->cra_name,
+ strlen(core->cra_name));
+
+ alg->cra_priority = priority;
+ priority++;
+ /*
+ * If FIPS mode enabled, the selected DRBG shall have the
+ * highest cra_priority over other stdrng instances to ensure
+ * it is selected.
+ */
+ if (fips_enabled)
+ alg->cra_priority += 200;
+
+ alg->cra_flags = CRYPTO_ALG_TYPE_RNG;
+ alg->cra_ctxsize = sizeof(struct drbg_state);
+ alg->cra_type = &crypto_rng_type;
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = drbg_kcapi_init;
+ alg->cra_exit = drbg_kcapi_cleanup;
+ alg->cra_u.rng.rng_make_random = drbg_kcapi_random;
+ alg->cra_u.rng.rng_reset = drbg_kcapi_reset;
+ alg->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: %zu, slots available: %zu)\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.
+ *
+ * As the order of placing them into the drbg_algs array matters
+ * (the later DRBGs receive a higher cra_priority) we register the
+ * prediction resistance DRBGs first as the should not be too
+ * interesting.
+ */
+ for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+ drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
+ for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+ drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+static void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+#ifndef CRYPTO_DRBG_HASH_STRING
+#define CRYPTO_DRBG_HASH_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_HMAC_STRING
+#define CRYPTO_DRBG_HMAC_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_CTR_STRING
+#define CRYPTO_DRBG_CTR_STRING ""
+#endif
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
+ "using following cores: "
+ CRYPTO_DRBG_HASH_STRING
+ CRYPTO_DRBG_HMAC_STRING
+ CRYPTO_DRBG_CTR_STRING);
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index 42ce9f570aec..bf7ab4a89493 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -68,7 +68,7 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
struct ablkcipher_request *subreq;
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
struct scatterlist *osrc, *odst;
struct scatterlist *dst;
@@ -86,7 +86,7 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
giv = req->giv;
- complete = req->creq.base.complete;
+ compl = req->creq.base.complete;
data = req->creq.base.data;
osrc = req->creq.src;
@@ -101,11 +101,11 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
if (vsrc != giv + ivsize && vdst != giv + ivsize) {
giv = PTR_ALIGN((u8 *)reqctx->tail,
crypto_ablkcipher_alignmask(geniv) + 1);
- complete = eseqiv_complete;
+ compl = eseqiv_complete;
data = req;
}
- ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
data);
sg_init_table(reqctx->src, 2);
diff --git a/crypto/gcm.c b/crypto/gcm.c
index b4f017939004..276cdac567b6 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -228,14 +228,14 @@ static void gcm_hash_final_done(struct crypto_async_request *areq, int err);
static int gcm_hash_update(struct aead_request *req,
struct crypto_gcm_req_priv_ctx *pctx,
- crypto_completion_t complete,
+ crypto_completion_t compl,
struct scatterlist *src,
unsigned int len)
{
struct ahash_request *ahreq = &pctx->u.ahreq;
ahash_request_set_callback(ahreq, aead_request_flags(req),
- complete, req);
+ compl, req);
ahash_request_set_crypt(ahreq, src, NULL, len);
return crypto_ahash_update(ahreq);
@@ -244,12 +244,12 @@ static int gcm_hash_update(struct aead_request *req,
static int gcm_hash_remain(struct aead_request *req,
struct crypto_gcm_req_priv_ctx *pctx,
unsigned int remain,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct ahash_request *ahreq = &pctx->u.ahreq;
ahash_request_set_callback(ahreq, aead_request_flags(req),
- complete, req);
+ compl, req);
sg_init_one(pctx->src, gcm_zeroes, remain);
ahash_request_set_crypt(ahreq, pctx->src, NULL, remain);
@@ -375,14 +375,14 @@ static void __gcm_hash_assoc_remain_done(struct aead_request *req, int err)
{
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
- crypto_completion_t complete;
+ crypto_completion_t compl;
unsigned int remain = 0;
if (!err && gctx->cryptlen) {
remain = gcm_remain(gctx->cryptlen);
- complete = remain ? gcm_hash_crypt_done :
+ compl = remain ? gcm_hash_crypt_done :
gcm_hash_crypt_remain_done;
- err = gcm_hash_update(req, pctx, complete,
+ err = gcm_hash_update(req, pctx, compl,
gctx->src, gctx->cryptlen);
if (err == -EINPROGRESS || err == -EBUSY)
return;
@@ -429,14 +429,14 @@ static void gcm_hash_assoc_done(struct crypto_async_request *areq, int err)
static void __gcm_hash_init_done(struct aead_request *req, int err)
{
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
unsigned int remain = 0;
if (!err && req->assoclen) {
remain = gcm_remain(req->assoclen);
- complete = remain ? gcm_hash_assoc_done :
+ compl = remain ? gcm_hash_assoc_done :
gcm_hash_assoc_remain_done;
- err = gcm_hash_update(req, pctx, complete,
+ err = gcm_hash_update(req, pctx, compl,
req->assoc, req->assoclen);
if (err == -EINPROGRESS || err == -EBUSY)
return;
@@ -462,7 +462,7 @@ static int gcm_hash(struct aead_request *req,
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
unsigned int remain;
- crypto_completion_t complete;
+ crypto_completion_t compl;
int err;
ahash_request_set_tfm(ahreq, ctx->ghash);
@@ -473,8 +473,8 @@ static int gcm_hash(struct aead_request *req,
if (err)
return err;
remain = gcm_remain(req->assoclen);
- complete = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
- err = gcm_hash_update(req, pctx, complete, req->assoc, req->assoclen);
+ compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
+ err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen);
if (err)
return err;
if (remain) {
@@ -484,8 +484,8 @@ static int gcm_hash(struct aead_request *req,
return err;
}
remain = gcm_remain(gctx->cryptlen);
- complete = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
- err = gcm_hash_update(req, pctx, complete, gctx->src, gctx->cryptlen);
+ compl = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
+ err = gcm_hash_update(req, pctx, compl, gctx->src, gctx->cryptlen);
if (err)
return err;
if (remain) {
diff --git a/crypto/lz4.c b/crypto/lz4.c
index 4586dd15b0d8..34d072b72a73 100644
--- a/crypto/lz4.c
+++ b/crypto/lz4.c
@@ -68,7 +68,7 @@ static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
size_t tmp_len = *dlen;
size_t __slen = slen;
- err = lz4_decompress(src, &__slen, dst, tmp_len);
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
if (err < 0)
return -EINVAL;
diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c
index 151ba31d34e3..9218b3fed5e3 100644
--- a/crypto/lz4hc.c
+++ b/crypto/lz4hc.c
@@ -68,7 +68,7 @@ static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
size_t tmp_len = *dlen;
size_t __slen = slen;
- err = lz4_decompress(src, &__slen, dst, tmp_len);
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
if (err < 0)
return -EINVAL;
diff --git a/crypto/lzo.c b/crypto/lzo.c
index 1c2aa69c54b8..a8ff2f778dc4 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <linux/lzo.h>
struct lzo_ctx {
@@ -30,7 +31,10 @@ static int lzo_init(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
+ ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+ if (!ctx->lzo_comp_mem)
+ ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
if (!ctx->lzo_comp_mem)
return -ENOMEM;
@@ -41,7 +45,7 @@ static void lzo_exit(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- vfree(ctx->lzo_comp_mem);
+ kvfree(ctx->lzo_comp_mem);
}
static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
new file mode 100644
index 000000000000..b39fbd530102
--- /dev/null
+++ b/crypto/mcryptd.c
@@ -0,0 +1,705 @@
+/*
+ * Software multibuffer async crypto daemon.
+ *
+ * Copyright (c) 2014 Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * Adapted from crypto daemon.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/aead.h>
+#include <crypto/mcryptd.h>
+#include <crypto/crypto_wq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+
+#define MCRYPTD_MAX_CPU_QLEN 100
+#define MCRYPTD_BATCH 9
+
+static void *mcryptd_alloc_instance(struct crypto_alg *alg, unsigned int head,
+ unsigned int tail);
+
+struct mcryptd_flush_list {
+ struct list_head list;
+ struct mutex lock;
+};
+
+static struct mcryptd_flush_list __percpu *mcryptd_flist;
+
+struct hashd_instance_ctx {
+ struct crypto_shash_spawn spawn;
+ struct mcryptd_queue *queue;
+};
+
+static void mcryptd_queue_worker(struct work_struct *work);
+
+void mcryptd_arm_flusher(struct mcryptd_alg_cstate *cstate, unsigned long delay)
+{
+ struct mcryptd_flush_list *flist;
+
+ if (!cstate->flusher_engaged) {
+ /* put the flusher on the flush list */
+ flist = per_cpu_ptr(mcryptd_flist, smp_processor_id());
+ mutex_lock(&flist->lock);
+ list_add_tail(&cstate->flush_list, &flist->list);
+ cstate->flusher_engaged = true;
+ cstate->next_flush = jiffies + delay;
+ queue_delayed_work_on(smp_processor_id(), kcrypto_wq,
+ &cstate->flush, delay);
+ mutex_unlock(&flist->lock);
+ }
+}
+EXPORT_SYMBOL(mcryptd_arm_flusher);
+
+static int mcryptd_init_queue(struct mcryptd_queue *queue,
+ unsigned int max_cpu_qlen)
+{
+ int cpu;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ queue->cpu_queue = alloc_percpu(struct mcryptd_cpu_queue);
+ pr_debug("mqueue:%p mcryptd_cpu_queue %p\n", queue, queue->cpu_queue);
+ if (!queue->cpu_queue)
+ return -ENOMEM;
+ for_each_possible_cpu(cpu) {
+ cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+ pr_debug("cpu_queue #%d %p\n", cpu, queue->cpu_queue);
+ crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
+ INIT_WORK(&cpu_queue->work, mcryptd_queue_worker);
+ }
+ return 0;
+}
+
+static void mcryptd_fini_queue(struct mcryptd_queue *queue)
+{
+ int cpu;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ for_each_possible_cpu(cpu) {
+ cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+ BUG_ON(cpu_queue->queue.qlen);
+ }
+ free_percpu(queue->cpu_queue);
+}
+
+static int mcryptd_enqueue_request(struct mcryptd_queue *queue,
+ struct crypto_async_request *request,
+ struct mcryptd_hash_request_ctx *rctx)
+{
+ int cpu, err;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ cpu = get_cpu();
+ cpu_queue = this_cpu_ptr(queue->cpu_queue);
+ rctx->tag.cpu = cpu;
+
+ err = crypto_enqueue_request(&cpu_queue->queue, request);
+ pr_debug("enqueue request: cpu %d cpu_queue %p request %p\n",
+ cpu, cpu_queue, request);
+ queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
+ put_cpu();
+
+ return err;
+}
+
+/*
+ * Try to opportunisticlly flush the partially completed jobs if
+ * crypto daemon is the only task running.
+ */
+static void mcryptd_opportunistic_flush(void)
+{
+ struct mcryptd_flush_list *flist;
+ struct mcryptd_alg_cstate *cstate;
+
+ flist = per_cpu_ptr(mcryptd_flist, smp_processor_id());
+ while (single_task_running()) {
+ mutex_lock(&flist->lock);
+ if (list_empty(&flist->list)) {
+ mutex_unlock(&flist->lock);
+ return;
+ }
+ cstate = list_entry(flist->list.next,
+ struct mcryptd_alg_cstate, flush_list);
+ if (!cstate->flusher_engaged) {
+ mutex_unlock(&flist->lock);
+ return;
+ }
+ list_del(&cstate->flush_list);
+ cstate->flusher_engaged = false;
+ mutex_unlock(&flist->lock);
+ cstate->alg_state->flusher(cstate);
+ }
+}
+
+/*
+ * Called in workqueue context, do one real cryption work (via
+ * req->complete) and reschedule itself if there are more work to
+ * do.
+ */
+static void mcryptd_queue_worker(struct work_struct *work)
+{
+ struct mcryptd_cpu_queue *cpu_queue;
+ struct crypto_async_request *req, *backlog;
+ int i;
+
+ /*
+ * Need to loop through more than once for multi-buffer to
+ * be effective.
+ */
+
+ cpu_queue = container_of(work, struct mcryptd_cpu_queue, work);
+ i = 0;
+ while (i < MCRYPTD_BATCH || single_task_running()) {
+ /*
+ * preempt_disable/enable is used to prevent
+ * being preempted by mcryptd_enqueue_request()
+ */
+ local_bh_disable();
+ preempt_disable();
+ backlog = crypto_get_backlog(&cpu_queue->queue);
+ req = crypto_dequeue_request(&cpu_queue->queue);
+ preempt_enable();
+ local_bh_enable();
+
+ if (!req) {
+ mcryptd_opportunistic_flush();
+ return;
+ }
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+ req->complete(req, 0);
+ if (!cpu_queue->queue.qlen)
+ return;
+ ++i;
+ }
+ if (cpu_queue->queue.qlen)
+ queue_work(kcrypto_wq, &cpu_queue->work);
+}
+
+void mcryptd_flusher(struct work_struct *__work)
+{
+ struct mcryptd_alg_cstate *alg_cpu_state;
+ struct mcryptd_alg_state *alg_state;
+ struct mcryptd_flush_list *flist;
+ int cpu;
+
+ cpu = smp_processor_id();
+ alg_cpu_state = container_of(to_delayed_work(__work),
+ struct mcryptd_alg_cstate, flush);
+ alg_state = alg_cpu_state->alg_state;
+ if (alg_cpu_state->cpu != cpu)
+ pr_debug("mcryptd error: work on cpu %d, should be cpu %d\n",
+ cpu, alg_cpu_state->cpu);
+
+ if (alg_cpu_state->flusher_engaged) {
+ flist = per_cpu_ptr(mcryptd_flist, cpu);
+ mutex_lock(&flist->lock);
+ list_del(&alg_cpu_state->flush_list);
+ alg_cpu_state->flusher_engaged = false;
+ mutex_unlock(&flist->lock);
+ alg_state->flusher(alg_cpu_state);
+ }
+}
+EXPORT_SYMBOL_GPL(mcryptd_flusher);
+
+static inline struct mcryptd_queue *mcryptd_get_queue(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct mcryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+
+ return ictx->queue;
+}
+
+static void *mcryptd_alloc_instance(struct crypto_alg *alg, unsigned int head,
+ unsigned int tail)
+{
+ char *p;
+ struct crypto_instance *inst;
+ int err;
+
+ p = kzalloc(head + sizeof(*inst) + tail, GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ inst = (void *)(p + head);
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "mcryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+ goto out_free_inst;
+
+ memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+
+ inst->alg.cra_priority = alg->cra_priority + 50;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+
+out:
+ return p;
+
+out_free_inst:
+ kfree(p);
+ p = ERR_PTR(err);
+ goto out;
+}
+
+static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct hashd_instance_ctx *ictx = crypto_instance_ctx(inst);
+ struct crypto_shash_spawn *spawn = &ictx->spawn;
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_shash *hash;
+
+ hash = crypto_spawn_shash(spawn);
+ if (IS_ERR(hash))
+ return PTR_ERR(hash);
+
+ ctx->child = hash;
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct mcryptd_hash_request_ctx) +
+ crypto_shash_descsize(hash));
+ return 0;
+}
+
+static void mcryptd_hash_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_shash(ctx->child);
+}
+
+static int mcryptd_hash_setkey(struct crypto_ahash *parent,
+ const u8 *key, unsigned int keylen)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(parent);
+ struct crypto_shash *child = ctx->child;
+ int err;
+
+ crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_shash_setkey(child, key, keylen);
+ crypto_ahash_set_flags(parent, crypto_shash_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+ return err;
+}
+
+static int mcryptd_hash_enqueue(struct ahash_request *req,
+ crypto_completion_t complete)
+{
+ int ret;
+
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct mcryptd_queue *queue =
+ mcryptd_get_queue(crypto_ahash_tfm(tfm));
+
+ rctx->complete = req->base.complete;
+ req->base.complete = complete;
+
+ ret = mcryptd_enqueue_request(queue, &req->base, rctx);
+
+ return ret;
+}
+
+static void mcryptd_hash_init(struct crypto_async_request *req_async, int err)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
+ struct crypto_shash *child = ctx->child;
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct shash_desc *desc = &rctx->desc;
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ desc->tfm = child;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ err = crypto_shash_init(desc);
+
+ req->base.complete = rctx->complete;
+
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_init_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_init);
+}
+
+static void mcryptd_hash_update(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_update(req, &rctx->desc);
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_update_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_update);
+}
+
+static void mcryptd_hash_final(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_final(req, &rctx->desc);
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_final_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_final);
+}
+
+static void mcryptd_hash_finup(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_finup(req, &rctx->desc);
+
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_finup_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_finup);
+}
+
+static void mcryptd_hash_digest(struct crypto_async_request *req_async, int err)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
+ struct crypto_shash *child = ctx->child;
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct shash_desc *desc = &rctx->desc;
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ desc->tfm = child;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; /* check this again */
+
+ err = shash_ahash_mcryptd_digest(req, desc);
+
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_digest_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_digest);
+}
+
+static int mcryptd_hash_export(struct ahash_request *req, void *out)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ return crypto_shash_export(&rctx->desc, out);
+}
+
+static int mcryptd_hash_import(struct ahash_request *req, const void *in)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ return crypto_shash_import(&rctx->desc, in);
+}
+
+static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
+ struct mcryptd_queue *queue)
+{
+ struct hashd_instance_ctx *ctx;
+ struct ahash_instance *inst;
+ struct shash_alg *salg;
+ struct crypto_alg *alg;
+ int err;
+
+ salg = shash_attr_alg(tb[1], 0, 0);
+ if (IS_ERR(salg))
+ return PTR_ERR(salg);
+
+ alg = &salg->base;
+ pr_debug("crypto: mcryptd hash alg: %s\n", alg->cra_name);
+ inst = mcryptd_alloc_instance(alg, ahash_instance_headroom(),
+ sizeof(*ctx));
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ ctx = ahash_instance_ctx(inst);
+ ctx->queue = queue;
+
+ err = crypto_init_shash_spawn(&ctx->spawn, salg,
+ ahash_crypto_instance(inst));
+ if (err)
+ goto out_free_inst;
+
+ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC;
+
+ inst->alg.halg.digestsize = salg->digestsize;
+ inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx);
+
+ inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm;
+ inst->alg.halg.base.cra_exit = mcryptd_hash_exit_tfm;
+
+ inst->alg.init = mcryptd_hash_init_enqueue;
+ inst->alg.update = mcryptd_hash_update_enqueue;
+ inst->alg.final = mcryptd_hash_final_enqueue;
+ inst->alg.finup = mcryptd_hash_finup_enqueue;
+ inst->alg.export = mcryptd_hash_export;
+ inst->alg.import = mcryptd_hash_import;
+ inst->alg.setkey = mcryptd_hash_setkey;
+ inst->alg.digest = mcryptd_hash_digest_enqueue;
+
+ err = ahash_register_instance(tmpl, inst);
+ if (err) {
+ crypto_drop_shash(&ctx->spawn);
+out_free_inst:
+ kfree(inst);
+ }
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return err;
+}
+
+static struct mcryptd_queue mqueue;
+
+static int mcryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+
+ algt = crypto_get_attr_type(tb);
+ if (IS_ERR(algt))
+ return PTR_ERR(algt);
+
+ switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_DIGEST:
+ return mcryptd_create_hash(tmpl, tb, &mqueue);
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static void mcryptd_free(struct crypto_instance *inst)
+{
+ struct mcryptd_instance_ctx *ctx = crypto_instance_ctx(inst);
+ struct hashd_instance_ctx *hctx = crypto_instance_ctx(inst);
+
+ switch (inst->alg.cra_flags & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_AHASH:
+ crypto_drop_shash(&hctx->spawn);
+ kfree(ahash_instance(inst));
+ return;
+ default:
+ crypto_drop_spawn(&ctx->spawn);
+ kfree(inst);
+ }
+}
+
+static struct crypto_template mcryptd_tmpl = {
+ .name = "mcryptd",
+ .create = mcryptd_create,
+ .free = mcryptd_free,
+ .module = THIS_MODULE,
+};
+
+struct mcryptd_ahash *mcryptd_alloc_ahash(const char *alg_name,
+ u32 type, u32 mask)
+{
+ char mcryptd_alg_name[CRYPTO_MAX_ALG_NAME];
+ struct crypto_ahash *tfm;
+
+ if (snprintf(mcryptd_alg_name, CRYPTO_MAX_ALG_NAME,
+ "mcryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-EINVAL);
+ tfm = crypto_alloc_ahash(mcryptd_alg_name, type, mask);
+ if (IS_ERR(tfm))
+ return ERR_CAST(tfm);
+ if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
+ crypto_free_ahash(tfm);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return __mcryptd_ahash_cast(tfm);
+}
+EXPORT_SYMBOL_GPL(mcryptd_alloc_ahash);
+
+int shash_ahash_mcryptd_digest(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ int err;
+
+ err = crypto_shash_init(desc) ?:
+ shash_ahash_mcryptd_finup(req, desc);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_digest);
+
+int shash_ahash_mcryptd_update(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->update(desc, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_update);
+
+int shash_ahash_mcryptd_finup(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->finup(desc, NULL, 0, req->result);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_finup);
+
+int shash_ahash_mcryptd_final(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->final(desc, req->result);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_final);
+
+struct crypto_shash *mcryptd_ahash_child(struct mcryptd_ahash *tfm)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
+
+ return ctx->child;
+}
+EXPORT_SYMBOL_GPL(mcryptd_ahash_child);
+
+struct shash_desc *mcryptd_shash_desc(struct ahash_request *req)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ return &rctx->desc;
+}
+EXPORT_SYMBOL_GPL(mcryptd_shash_desc);
+
+void mcryptd_free_ahash(struct mcryptd_ahash *tfm)
+{
+ crypto_free_ahash(&tfm->base);
+}
+EXPORT_SYMBOL_GPL(mcryptd_free_ahash);
+
+
+static int __init mcryptd_init(void)
+{
+ int err, cpu;
+ struct mcryptd_flush_list *flist;
+
+ mcryptd_flist = alloc_percpu(struct mcryptd_flush_list);
+ for_each_possible_cpu(cpu) {
+ flist = per_cpu_ptr(mcryptd_flist, cpu);
+ INIT_LIST_HEAD(&flist->list);
+ mutex_init(&flist->lock);
+ }
+
+ err = mcryptd_init_queue(&mqueue, MCRYPTD_MAX_CPU_QLEN);
+ if (err) {
+ free_percpu(mcryptd_flist);
+ return err;
+ }
+
+ err = crypto_register_template(&mcryptd_tmpl);
+ if (err) {
+ mcryptd_fini_queue(&mqueue);
+ free_percpu(mcryptd_flist);
+ }
+
+ return err;
+}
+
+static void __exit mcryptd_exit(void)
+{
+ mcryptd_fini_queue(&mqueue);
+ crypto_unregister_template(&mcryptd_tmpl);
+ free_percpu(mcryptd_flist);
+}
+
+subsys_initcall(mcryptd_init);
+module_exit(mcryptd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Software async multibuffer crypto daemon");
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index f2cba4ed6f25..ee190fcedcd2 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -100,7 +100,7 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
u8 *info;
unsigned int ivsize;
@@ -108,7 +108,7 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
- complete = req->creq.base.complete;
+ compl = req->creq.base.complete;
data = req->creq.base.data;
info = req->creq.info;
@@ -122,11 +122,11 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
if (!info)
return -ENOMEM;
- complete = seqiv_complete;
+ compl = seqiv_complete;
data = req;
}
- ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
data);
ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
req->creq.nbytes, info);
@@ -146,7 +146,7 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
struct aead_request *areq = &req->areq;
struct aead_request *subreq = aead_givcrypt_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
u8 *info;
unsigned int ivsize;
@@ -154,7 +154,7 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
aead_request_set_tfm(subreq, aead_geniv_base(geniv));
- complete = areq->base.complete;
+ compl = areq->base.complete;
data = areq->base.data;
info = areq->iv;
@@ -168,11 +168,11 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
if (!info)
return -ENOMEM;
- complete = seqiv_aead_complete;
+ compl = seqiv_aead_complete;
data = req;
}
- aead_request_set_callback(subreq, areq->base.flags, complete, data);
+ aead_request_set_callback(subreq, areq->base.flags, compl, data);
aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
info);
aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index 543366779524..0bb558344699 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -24,6 +24,7 @@
#include <linux/types.h>
#include <crypto/sha.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
static inline u32 Ch(u32 x, u32 y, u32 z)
{
@@ -42,7 +43,7 @@ static inline u32 Maj(u32 x, u32 y, u32 z)
static inline void LOAD_OP(int I, u32 *W, const u8 *input)
{
- W[I] = __be32_to_cpu( ((__be32*)(input))[I] );
+ W[I] = get_unaligned_be32((__u32 *)input + I);
}
static inline void BLEND_OP(int I, u32 *W)
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 6ed124f3ea0f..6dde57dc511b 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -20,6 +20,7 @@
#include <crypto/sha.h>
#include <linux/percpu.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
static inline u64 Ch(u64 x, u64 y, u64 z)
{
@@ -68,7 +69,7 @@ static const u64 sha512_K[80] = {
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
- W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
+ W[I] = get_unaligned_be64((__u64 *)input + I);
}
static inline void BLEND_OP(int I, u64 *W)
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index ba247cf30858..890449e6e7ef 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -48,6 +48,11 @@
#define DECRYPT 0
/*
+ * return a string with the driver name
+ */
+#define get_driver_name(tfm_type, tfm) crypto_tfm_alg_driver_name(tfm_type ## _tfm(tfm))
+
+/*
* Used by test_cipher_speed()
*/
static unsigned int sec;
@@ -68,13 +73,13 @@ static char *check[] = {
};
static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
- struct scatterlist *sg, int blen, int sec)
+ struct scatterlist *sg, int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
@@ -86,7 +91,7 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
}
printk("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -138,13 +143,13 @@ out:
}
static int test_aead_jiffies(struct aead_request *req, int enc,
- int blen, int sec)
+ int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = crypto_aead_encrypt(req);
@@ -156,7 +161,7 @@ static int test_aead_jiffies(struct aead_request *req, int enc,
}
printk("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -260,7 +265,7 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE],
}
}
-static void test_aead_speed(const char *algo, int enc, unsigned int sec,
+static void test_aead_speed(const char *algo, int enc, unsigned int secs,
struct aead_speed_template *template,
unsigned int tcount, u8 authsize,
unsigned int aad_size, u8 *keysize)
@@ -305,9 +310,6 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
asg = &sg[8];
sgout = &asg[8];
-
- printk(KERN_INFO "\ntesting speed of %s %s\n", algo, e);
-
tfm = crypto_alloc_aead(algo, 0, 0);
if (IS_ERR(tfm)) {
@@ -316,6 +318,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
goto out_notfm;
}
+ printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+ get_driver_name(crypto_aead, tfm), e);
+
req = aead_request_alloc(tfm, GFP_KERNEL);
if (!req) {
pr_err("alg: aead: Failed to allocate request for %s\n",
@@ -374,8 +379,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
aead_request_set_crypt(req, sg, sgout, *b_size, iv);
aead_request_set_assoc(req, asg, aad_size);
- if (sec)
- ret = test_aead_jiffies(req, enc, *b_size, sec);
+ if (secs)
+ ret = test_aead_jiffies(req, enc, *b_size,
+ secs);
else
ret = test_aead_cycles(req, enc, *b_size);
@@ -405,7 +411,7 @@ out_noxbuf:
return;
}
-static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
struct cipher_speed_template *template,
unsigned int tcount, u8 *keysize)
{
@@ -422,8 +428,6 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
else
e = "decryption";
- printk("\ntesting speed of %s %s\n", algo, e);
-
tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
@@ -434,6 +438,9 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
desc.tfm = tfm;
desc.flags = 0;
+ printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+ get_driver_name(crypto_blkcipher, tfm), e);
+
i = 0;
do {
@@ -483,9 +490,9 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
crypto_blkcipher_set_iv(tfm, iv, iv_len);
}
- if (sec)
+ if (secs)
ret = test_cipher_jiffies(&desc, enc, sg,
- *b_size, sec);
+ *b_size, secs);
else
ret = test_cipher_cycles(&desc, enc, sg,
*b_size);
@@ -506,13 +513,13 @@ out:
static int test_hash_jiffies_digest(struct hash_desc *desc,
struct scatterlist *sg, int blen,
- char *out, int sec)
+ char *out, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_hash_digest(desc, sg, blen, out);
if (ret)
@@ -520,22 +527,22 @@ static int test_hash_jiffies_digest(struct hash_desc *desc,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
- int blen, int plen, char *out, int sec)
+ int blen, int plen, char *out, int secs)
{
unsigned long start, end;
int bcount, pcount;
int ret;
if (plen == blen)
- return test_hash_jiffies_digest(desc, sg, blen, out, sec);
+ return test_hash_jiffies_digest(desc, sg, blen, out, secs);
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_hash_init(desc);
if (ret)
@@ -552,7 +559,7 @@ static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
@@ -673,7 +680,7 @@ static void test_hash_sg_init(struct scatterlist *sg)
}
}
-static void test_hash_speed(const char *algo, unsigned int sec,
+static void test_hash_speed(const char *algo, unsigned int secs,
struct hash_speed *speed)
{
struct scatterlist sg[TVMEMSIZE];
@@ -683,8 +690,6 @@ static void test_hash_speed(const char *algo, unsigned int sec,
int i;
int ret;
- printk(KERN_INFO "\ntesting speed of %s\n", algo);
-
tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
@@ -693,6 +698,9 @@ static void test_hash_speed(const char *algo, unsigned int sec,
return;
}
+ printk(KERN_INFO "\ntesting speed of %s (%s)\n", algo,
+ get_driver_name(crypto_hash, tfm));
+
desc.tfm = tfm;
desc.flags = 0;
@@ -718,9 +726,9 @@ static void test_hash_speed(const char *algo, unsigned int sec,
"(%5u byte blocks,%5u bytes per update,%4u updates): ",
i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
- if (sec)
+ if (secs)
ret = test_hash_jiffies(&desc, sg, speed[i].blen,
- speed[i].plen, output, sec);
+ speed[i].plen, output, secs);
else
ret = test_hash_cycles(&desc, sg, speed[i].blen,
speed[i].plen, output);
@@ -765,13 +773,13 @@ static inline int do_one_ahash_op(struct ahash_request *req, int ret)
}
static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
- char *out, int sec)
+ char *out, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = do_one_ahash_op(req, crypto_ahash_digest(req));
if (ret)
@@ -779,22 +787,22 @@ static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
static int test_ahash_jiffies(struct ahash_request *req, int blen,
- int plen, char *out, int sec)
+ int plen, char *out, int secs)
{
unsigned long start, end;
int bcount, pcount;
int ret;
if (plen == blen)
- return test_ahash_jiffies_digest(req, blen, out, sec);
+ return test_ahash_jiffies_digest(req, blen, out, secs);
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_ahash_init(req);
if (ret)
@@ -811,7 +819,7 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen,
}
pr_cont("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
@@ -911,7 +919,7 @@ out:
return 0;
}
-static void test_ahash_speed(const char *algo, unsigned int sec,
+static void test_ahash_speed(const char *algo, unsigned int secs,
struct hash_speed *speed)
{
struct scatterlist sg[TVMEMSIZE];
@@ -921,8 +929,6 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
static char output[1024];
int i, ret;
- printk(KERN_INFO "\ntesting speed of async %s\n", algo);
-
tfm = crypto_alloc_ahash(algo, 0, 0);
if (IS_ERR(tfm)) {
pr_err("failed to load transform for %s: %ld\n",
@@ -930,6 +936,9 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
return;
}
+ printk(KERN_INFO "\ntesting speed of async %s (%s)\n", algo,
+ get_driver_name(crypto_ahash, tfm));
+
if (crypto_ahash_digestsize(tfm) > sizeof(output)) {
pr_err("digestsize(%u) > outputbuffer(%zu)\n",
crypto_ahash_digestsize(tfm), sizeof(output));
@@ -960,9 +969,9 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
ahash_request_set_crypt(req, sg, output, speed[i].plen);
- if (sec)
+ if (secs)
ret = test_ahash_jiffies(req, speed[i].blen,
- speed[i].plen, output, sec);
+ speed[i].plen, output, secs);
else
ret = test_ahash_cycles(req, speed[i].blen,
speed[i].plen, output);
@@ -994,13 +1003,13 @@ static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
}
static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
- int blen, int sec)
+ int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = do_one_acipher_op(req,
@@ -1014,7 +1023,7 @@ static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
}
pr_cont("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -1065,7 +1074,7 @@ out:
return ret;
}
-static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
struct cipher_speed_template *template,
unsigned int tcount, u8 *keysize)
{
@@ -1083,8 +1092,6 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
else
e = "decryption";
- pr_info("\ntesting speed of async %s %s\n", algo, e);
-
init_completion(&tresult.completion);
tfm = crypto_alloc_ablkcipher(algo, 0, 0);
@@ -1095,6 +1102,9 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
return;
}
+ pr_info("\ntesting speed of async %s (%s) %s\n", algo,
+ get_driver_name(crypto_ablkcipher, tfm), e);
+
req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) {
pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
@@ -1168,9 +1178,9 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv);
- if (sec)
+ if (secs)
ret = test_acipher_jiffies(req, enc,
- *b_size, sec);
+ *b_size, secs);
else
ret = test_acipher_cycles(req, enc,
*b_size);
@@ -1585,6 +1595,12 @@ static int do_test(int m)
test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
+ test_cipher_speed("ctr(des3_ede)", ENCRYPT, sec,
+ des3_speed_template, DES3_SPEED_VECTORS,
+ speed_template_24);
+ test_cipher_speed("ctr(des3_ede)", DECRYPT, sec,
+ des3_speed_template, DES3_SPEED_VECTORS,
+ speed_template_24);
break;
case 202:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 498649ac1953..9459dfd7357f 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;
};
@@ -171,9 +178,7 @@ static void testmgr_free_buf(char *buf[XBUFSIZE])
free_page((unsigned long)buf[i]);
}
-static int do_one_async_hash_op(struct ahash_request *req,
- struct tcrypt_result *tr,
- int ret)
+static int wait_async_op(struct tcrypt_result *tr, int ret)
{
if (ret == -EINPROGRESS || ret == -EBUSY) {
ret = wait_for_completion_interruptible(&tr->completion);
@@ -191,13 +196,20 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
unsigned int i, j, k, temp;
struct scatterlist sg[8];
- char result[64];
+ char *result;
+ char *key;
struct ahash_request *req;
struct tcrypt_result tresult;
void *hash_buff;
char *xbuf[XBUFSIZE];
int ret = -ENOMEM;
+ result = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
+ if (!result)
+ return ret;
+ key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+ if (!key)
+ goto out_nobuf;
if (testmgr_alloc_buf(xbuf))
goto out_nobuf;
@@ -222,7 +234,7 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
goto out;
j++;
- memset(result, 0, 64);
+ memset(result, 0, MAX_DIGEST_SIZE);
hash_buff = xbuf[0];
hash_buff += align_offset;
@@ -232,8 +244,14 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (template[i].ksize) {
crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
- template[i].ksize);
+ if (template[i].ksize > MAX_KEYLEN) {
+ pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+ j, algo, template[i].ksize, MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].ksize);
+ ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
if (ret) {
printk(KERN_ERR "alg: hash: setkey failed on "
"test %d for %s: ret=%d\n", j, algo,
@@ -244,30 +262,26 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
ahash_request_set_crypt(req, sg, result, template[i].psize);
if (use_digest) {
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_digest(req));
+ ret = wait_async_op(&tresult, crypto_ahash_digest(req));
if (ret) {
pr_err("alg: hash: digest failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
} else {
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_init(req));
+ ret = wait_async_op(&tresult, crypto_ahash_init(req));
if (ret) {
pr_err("alt: hash: init failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_update(req));
+ ret = wait_async_op(&tresult, crypto_ahash_update(req));
if (ret) {
pr_err("alt: hash: update failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_final(req));
+ ret = wait_async_op(&tresult, crypto_ahash_final(req));
if (ret) {
pr_err("alt: hash: final failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
@@ -291,70 +305,75 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (align_offset != 0)
break;
- if (template[i].np) {
- j++;
- memset(result, 0, 64);
+ if (!template[i].np)
+ continue;
- temp = 0;
- sg_init_table(sg, template[i].np);
- ret = -EINVAL;
- for (k = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
- sg_set_buf(&sg[k],
- memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].plaintext + temp,
- template[i].tap[k]),
- template[i].tap[k]);
- temp += template[i].tap[k];
- }
-
- if (template[i].ksize) {
- crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
- template[i].ksize);
-
- if (ret) {
- printk(KERN_ERR "alg: hash: setkey "
- "failed on chunking test %d "
- "for %s: ret=%d\n", j, algo,
- -ret);
- goto out;
- }
- }
-
- ahash_request_set_crypt(req, sg, result,
- template[i].psize);
- ret = crypto_ahash_digest(req);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &tresult.completion);
- if (!ret && !(ret = tresult.err)) {
- reinit_completion(&tresult.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: hash: digest failed "
- "on chunking test %d for %s: "
- "ret=%d\n", j, algo, -ret);
+ j++;
+ memset(result, 0, MAX_DIGEST_SIZE);
+
+ temp = 0;
+ sg_init_table(sg, template[i].np);
+ ret = -EINVAL;
+ for (k = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
goto out;
- }
+ sg_set_buf(&sg[k],
+ memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]),
+ template[i].plaintext + temp,
+ template[i].tap[k]),
+ template[i].tap[k]);
+ temp += template[i].tap[k];
+ }
- if (memcmp(result, template[i].digest,
- crypto_ahash_digestsize(tfm))) {
- printk(KERN_ERR "alg: hash: Chunking test %d "
- "failed for %s\n", j, algo);
- hexdump(result, crypto_ahash_digestsize(tfm));
+ if (template[i].ksize) {
+ if (template[i].ksize > MAX_KEYLEN) {
+ pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+ j, algo, template[i].ksize, MAX_KEYLEN);
ret = -EINVAL;
goto out;
}
+ crypto_ahash_clear_flags(tfm, ~0);
+ memcpy(key, template[i].key, template[i].ksize);
+ ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
+
+ if (ret) {
+ printk(KERN_ERR "alg: hash: setkey "
+ "failed on chunking test %d "
+ "for %s: ret=%d\n", j, algo, -ret);
+ goto out;
+ }
+ }
+
+ ahash_request_set_crypt(req, sg, result, template[i].psize);
+ ret = crypto_ahash_digest(req);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &tresult.completion);
+ if (!ret && !(ret = tresult.err)) {
+ reinit_completion(&tresult.completion);
+ break;
+ }
+ /* fall through */
+ default:
+ printk(KERN_ERR "alg: hash: digest failed "
+ "on chunking test %d for %s: "
+ "ret=%d\n", j, algo, -ret);
+ goto out;
+ }
+
+ if (memcmp(result, template[i].digest,
+ crypto_ahash_digestsize(tfm))) {
+ printk(KERN_ERR "alg: hash: Chunking test %d "
+ "failed for %s\n", j, algo);
+ hexdump(result, crypto_ahash_digestsize(tfm));
+ ret = -EINVAL;
+ goto out;
}
}
@@ -365,6 +384,8 @@ out:
out_noreq:
testmgr_free_buf(xbuf);
out_nobuf:
+ kfree(key);
+ kfree(result);
return ret;
}
@@ -422,6 +443,9 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
if (!iv)
return ret;
+ key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+ if (!key)
+ goto out_noxbuf;
if (testmgr_alloc_buf(xbuf))
goto out_noxbuf;
if (testmgr_alloc_buf(axbuf))
@@ -459,114 +483,116 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
tcrypt_complete, &result);
for (i = 0, j = 0; i < tcount; i++) {
- if (!template[i].np) {
- j++;
+ if (template[i].np)
+ continue;
- /* some templates have no input data but they will
- * touch input
- */
- input = xbuf[0];
- input += align_offset;
- assoc = axbuf[0];
+ j++;
- ret = -EINVAL;
- if (WARN_ON(align_offset + template[i].ilen >
- PAGE_SIZE || template[i].alen > PAGE_SIZE))
- goto out;
+ /* some templates have no input data but they will
+ * touch input
+ */
+ input = xbuf[0];
+ input += align_offset;
+ assoc = axbuf[0];
- memcpy(input, template[i].input, template[i].ilen);
- memcpy(assoc, template[i].assoc, template[i].alen);
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
+ ret = -EINVAL;
+ if (WARN_ON(align_offset + template[i].ilen >
+ PAGE_SIZE || template[i].alen > PAGE_SIZE))
+ goto out;
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ memcpy(input, template[i].input, template[i].ilen);
+ memcpy(assoc, template[i].assoc, template[i].alen);
+ if (template[i].iv)
+ memcpy(iv, template[i].iv, MAX_IVLEN);
+ else
+ memset(iv, 0, MAX_IVLEN);
- key = template[i].key;
+ crypto_aead_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- ret = crypto_aead_setkey(tfm, key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
- d, j, algo, crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen,
+ MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
- authsize = abs(template[i].rlen - template[i].ilen);
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
- d, authsize, j, algo);
- goto out;
- }
+ ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
+ d, j, algo, crypto_aead_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- if (diff_dst) {
- output = xoutbuf[0];
- output += align_offset;
- sg_init_one(&sg[0], input, template[i].ilen);
- sg_init_one(&sgout[0], output,
- template[i].rlen);
- } else {
- sg_init_one(&sg[0], input,
- template[i].ilen +
- (enc ? authsize : 0));
- output = input;
- }
+ authsize = abs(template[i].rlen - template[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
+ d, authsize, j, algo);
+ goto out;
+ }
- sg_init_one(&asg[0], assoc, template[i].alen);
+ if (diff_dst) {
+ output = xoutbuf[0];
+ output += align_offset;
+ sg_init_one(&sg[0], input, template[i].ilen);
+ sg_init_one(&sgout[0], output, template[i].rlen);
+ } else {
+ sg_init_one(&sg[0], input,
+ template[i].ilen + (enc ? authsize : 0));
+ output = input;
+ }
- aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
+ sg_init_one(&asg[0], assoc, template[i].alen);
- aead_request_set_assoc(req, asg, template[i].alen);
+ aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
+ aead_request_set_assoc(req, asg, template[i].alen);
- switch (ret) {
- case 0:
- if (template[i].novrfy) {
- /* verification was supposed to fail */
- pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
- d, e, j, algo);
- /* so really, we got a bad message */
- ret = -EBADMSG;
- goto out;
- }
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- reinit_completion(&result.completion);
- break;
- }
- case -EBADMSG:
- if (template[i].novrfy)
- /* verification failure was expected */
- continue;
- /* fall through */
- default:
- pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
- }
+ ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
- q = output;
- if (memcmp(q, template[i].result, template[i].rlen)) {
- pr_err("alg: aead%s: Test %d failed on %s for %s\n",
- d, j, e, algo);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
+ switch (ret) {
+ case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
+ d, e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
goto out;
}
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ reinit_completion(&result.completion);
+ break;
+ }
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
+ /* fall through */
+ default:
+ pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
+
+ q = output;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ pr_err("alg: aead%s: Test %d failed on %s for %s\n",
+ d, j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
}
}
@@ -575,184 +601,182 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
if (align_offset != 0)
break;
- if (template[i].np) {
- j++;
+ if (!template[i].np)
+ continue;
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = template[i].key;
-
- ret = crypto_aead_setkey(tfm, key, template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
- d, j, algo, crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ j++;
- authsize = abs(template[i].rlen - template[i].ilen);
+ if (template[i].iv)
+ memcpy(iv, template[i].iv, MAX_IVLEN);
+ else
+ memset(iv, 0, MAX_IVLEN);
+ crypto_aead_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen, MAX_KEYLEN);
ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- if (diff_dst)
- sg_init_table(sgout, template[i].np);
- for (k = 0, temp = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
-
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
+ ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
+ d, j, algo, crypto_aead_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- sg_set_buf(&sg[k], q, template[i].tap[k]);
+ authsize = abs(template[i].rlen - template[i].ilen);
- if (diff_dst) {
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ ret = -EINVAL;
+ sg_init_table(sg, template[i].np);
+ if (diff_dst)
+ sg_init_table(sgout, template[i].np);
+ for (k = 0, temp = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
+ goto out;
- memset(q, 0, template[i].tap[k]);
+ q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
+ memcpy(q, template[i].input + temp, template[i].tap[k]);
+ sg_set_buf(&sg[k], q, template[i].tap[k]);
- sg_set_buf(&sgout[k], q,
- template[i].tap[k]);
- }
+ if (diff_dst) {
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- n = template[i].tap[k];
- if (k == template[i].np - 1 && enc)
- n += authsize;
- if (offset_in_page(q) + n < PAGE_SIZE)
- q[n] = 0;
+ memset(q, 0, template[i].tap[k]);
- temp += template[i].tap[k];
+ sg_set_buf(&sgout[k], q, template[i].tap[k]);
}
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
- d, authsize, j, algo);
+ n = template[i].tap[k];
+ if (k == template[i].np - 1 && enc)
+ n += authsize;
+ if (offset_in_page(q) + n < PAGE_SIZE)
+ q[n] = 0;
+
+ temp += template[i].tap[k];
+ }
+
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
+ d, authsize, j, algo);
+ goto out;
+ }
+
+ if (enc) {
+ if (WARN_ON(sg[k - 1].offset +
+ sg[k - 1].length + authsize >
+ PAGE_SIZE)) {
+ ret = -EINVAL;
goto out;
}
- if (enc) {
- if (WARN_ON(sg[k - 1].offset +
- sg[k - 1].length + authsize >
- PAGE_SIZE)) {
- ret = -EINVAL;
- goto out;
- }
+ if (diff_dst)
+ sgout[k - 1].length += authsize;
+ else
+ sg[k - 1].length += authsize;
+ }
- if (diff_dst)
- sgout[k - 1].length += authsize;
- else
- sg[k - 1].length += authsize;
+ sg_init_table(asg, template[i].anp);
+ ret = -EINVAL;
+ for (k = 0, temp = 0; k < template[i].anp; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].atap[k] > PAGE_SIZE))
+ goto out;
+ sg_set_buf(&asg[k],
+ memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]),
+ template[i].assoc + temp,
+ template[i].atap[k]),
+ template[i].atap[k]);
+ temp += template[i].atap[k];
+ }
+
+ aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen,
+ iv);
+
+ aead_request_set_assoc(req, asg, template[i].alen);
+
+ ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
+
+ switch (ret) {
+ case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
+ d, e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
+ goto out;
}
-
- sg_init_table(asg, template[i].anp);
- ret = -EINVAL;
- for (k = 0, temp = 0; k < template[i].anp; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].atap[k] > PAGE_SIZE))
- goto out;
- sg_set_buf(&asg[k],
- memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].assoc + temp,
- template[i].atap[k]),
- template[i].atap[k]);
- temp += template[i].atap[k];
- }
-
- aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
- template[i].ilen,
- iv);
-
- aead_request_set_assoc(req, asg, template[i].alen);
-
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
-
- switch (ret) {
- case 0:
- if (template[i].novrfy) {
- /* verification was supposed to fail */
- pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
- d, e, j, algo);
- /* so really, we got a bad message */
- ret = -EBADMSG;
- goto out;
- }
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ reinit_completion(&result.completion);
break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- reinit_completion(&result.completion);
- break;
- }
- case -EBADMSG:
- if (template[i].novrfy)
- /* verification failure was expected */
- continue;
- /* fall through */
- default:
- pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
}
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
+ /* fall through */
+ default:
+ pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- ret = -EINVAL;
- for (k = 0, temp = 0; k < template[i].np; k++) {
- if (diff_dst)
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
- else
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- n = template[i].tap[k];
- if (k == template[i].np - 1)
- n += enc ? authsize : -authsize;
+ ret = -EINVAL;
+ for (k = 0, temp = 0; k < template[i].np; k++) {
+ if (diff_dst)
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
+ else
+ q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- if (memcmp(q, template[i].result + temp, n)) {
- pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
- d, j, e, k, algo);
- hexdump(q, n);
- goto out;
- }
+ n = template[i].tap[k];
+ if (k == template[i].np - 1)
+ n += enc ? authsize : -authsize;
- q += n;
- if (k == template[i].np - 1 && !enc) {
- if (!diff_dst &&
- memcmp(q, template[i].input +
- temp + n, authsize))
- n = authsize;
- else
- n = 0;
- } else {
- for (n = 0; offset_in_page(q + n) &&
- q[n]; n++)
- ;
- }
- if (n) {
- pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
- d, j, e, k, algo, n);
- hexdump(q, n);
- goto out;
- }
+ if (memcmp(q, template[i].result + temp, n)) {
+ pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
+ d, j, e, k, algo);
+ hexdump(q, n);
+ goto out;
+ }
- temp += template[i].tap[k];
+ q += n;
+ if (k == template[i].np - 1 && !enc) {
+ if (!diff_dst &&
+ memcmp(q, template[i].input +
+ temp + n, authsize))
+ n = authsize;
+ else
+ n = 0;
+ } else {
+ for (n = 0; offset_in_page(q + n) && q[n]; n++)
+ ;
+ }
+ if (n) {
+ pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
+ d, j, e, k, algo, n);
+ hexdump(q, n);
+ goto out;
}
+
+ temp += template[i].tap[k];
}
}
@@ -769,6 +793,7 @@ out_nooutbuf:
out_noaxbuf:
testmgr_free_buf(xbuf);
out_noxbuf:
+ kfree(key);
kfree(iv);
return ret;
}
@@ -930,78 +955,73 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
j = 0;
for (i = 0; i < tcount; i++) {
+ if (template[i].np && !template[i].also_non_np)
+ continue;
+
if (template[i].iv)
memcpy(iv, template[i].iv, MAX_IVLEN);
else
memset(iv, 0, MAX_IVLEN);
- if (!(template[i].np) || (template[i].also_non_np)) {
- j++;
+ j++;
+ ret = -EINVAL;
+ if (WARN_ON(align_offset + template[i].ilen > PAGE_SIZE))
+ goto out;
- ret = -EINVAL;
- if (WARN_ON(align_offset + template[i].ilen >
- PAGE_SIZE))
- goto out;
+ data = xbuf[0];
+ data += align_offset;
+ memcpy(data, template[i].input, template[i].ilen);
- data = xbuf[0];
- data += align_offset;
- memcpy(data, template[i].input, template[i].ilen);
-
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-
- ret = crypto_ablkcipher_setkey(tfm, template[i].key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
- d, j, algo,
- crypto_ablkcipher_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- sg_init_one(&sg[0], data, template[i].ilen);
- if (diff_dst) {
- data = xoutbuf[0];
- data += align_offset;
- sg_init_one(&sgout[0], data, template[i].ilen);
- }
+ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+ template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
+ d, j, algo, crypto_ablkcipher_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
+
+ sg_init_one(&sg[0], data, template[i].ilen);
+ if (diff_dst) {
+ data = xoutbuf[0];
+ data += align_offset;
+ sg_init_one(&sgout[0], data, template[i].ilen);
+ }
- ablkcipher_request_set_crypt(req, sg,
- (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
+ ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
+ ret = enc ? crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
- switch (ret) {
- case 0:
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !((ret = result.err))) {
+ reinit_completion(&result.completion);
break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- reinit_completion(&result.completion);
- break;
- }
- /* fall through */
- default:
- pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
}
+ /* fall through */
+ default:
+ pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- q = data;
- if (memcmp(q, template[i].result, template[i].rlen)) {
- pr_err("alg: skcipher%s: Test %d failed on %s for %s\n",
- d, j, e, algo);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
- goto out;
- }
+ q = data;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ pr_err("alg: skcipher%s: Test %d failed on %s for %s\n",
+ d, j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
}
}
@@ -1011,121 +1031,113 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
if (align_offset != 0)
break;
+ if (!template[i].np)
+ continue;
+
if (template[i].iv)
memcpy(iv, template[i].iv, MAX_IVLEN);
else
memset(iv, 0, MAX_IVLEN);
- if (template[i].np) {
- j++;
+ j++;
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+ template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
+ d, j, algo, crypto_ablkcipher_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- ret = crypto_ablkcipher_setkey(tfm, template[i].key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
- d, j, algo,
- crypto_ablkcipher_get_flags(tfm));
+ temp = 0;
+ ret = -EINVAL;
+ sg_init_table(sg, template[i].np);
+ if (diff_dst)
+ sg_init_table(sgout, template[i].np);
+ for (k = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
goto out;
- } else if (ret)
- continue;
- temp = 0;
- ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- if (diff_dst)
- sg_init_table(sgout, template[i].np);
- for (k = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
+ q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ memcpy(q, template[i].input + temp, template[i].tap[k]);
+
+ if (offset_in_page(q) + template[i].tap[k] < PAGE_SIZE)
+ q[template[i].tap[k]] = 0;
+
+ sg_set_buf(&sg[k], q, template[i].tap[k]);
+ if (diff_dst) {
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
offset_in_page(IDX[k]);
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
+ sg_set_buf(&sgout[k], q, template[i].tap[k]);
- if (offset_in_page(q) + template[i].tap[k] <
- PAGE_SIZE)
+ memset(q, 0, template[i].tap[k]);
+ if (offset_in_page(q) +
+ template[i].tap[k] < PAGE_SIZE)
q[template[i].tap[k]] = 0;
+ }
- sg_set_buf(&sg[k], q, template[i].tap[k]);
- if (diff_dst) {
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ temp += template[i].tap[k];
+ }
- sg_set_buf(&sgout[k], q,
- template[i].tap[k]);
+ ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
- memset(q, 0, template[i].tap[k]);
- if (offset_in_page(q) +
- template[i].tap[k] < PAGE_SIZE)
- q[template[i].tap[k]] = 0;
- }
+ ret = enc ? crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
- temp += template[i].tap[k];
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !((ret = result.err))) {
+ reinit_completion(&result.completion);
+ break;
}
+ /* fall through */
+ default:
+ pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- ablkcipher_request_set_crypt(req, sg,
- (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
-
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
+ temp = 0;
+ ret = -EINVAL;
+ for (k = 0; k < template[i].np; k++) {
+ if (diff_dst)
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
+ else
+ q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- reinit_completion(&result.completion);
- break;
- }
- /* fall through */
- default:
- pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
+ if (memcmp(q, template[i].result + temp,
+ template[i].tap[k])) {
+ pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
+ d, j, e, k, algo);
+ hexdump(q, template[i].tap[k]);
goto out;
}
- temp = 0;
- ret = -EINVAL;
- for (k = 0; k < template[i].np; k++) {
- if (diff_dst)
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
- else
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- if (memcmp(q, template[i].result + temp,
- template[i].tap[k])) {
- pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
- d, j, e, k, algo);
- hexdump(q, template[i].tap[k]);
- goto out;
- }
-
- q += template[i].tap[k];
- for (n = 0; offset_in_page(q + n) && q[n]; n++)
- ;
- if (n) {
- pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
- d, j, e, k, algo, n);
- hexdump(q, n);
- goto out;
- }
- temp += template[i].tap[k];
+ q += template[i].tap[k];
+ for (n = 0; offset_in_page(q + n) && q[n]; n++)
+ ;
+ if (n) {
+ pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
+ d, j, e, k, algo, n);
+ hexdump(q, n);
+ goto out;
}
+ temp += template[i].tap[k];
}
}
@@ -1715,6 +1727,100 @@ 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))
+ 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)
{
@@ -2458,6 +2564,152 @@ 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)
+ }
+ }
+ }, {
+ /* covered by drbg_nopr_hmac_sha256 test */
+ .alg = "drbg_nopr_hmac_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_nopr_hmac_sha512",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .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)
+ }
+ }
+ }, {
+ /* covered by drbg_nopr_sha256 test */
+ .alg = "drbg_nopr_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .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)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_ctr_aes128 test */
+ .alg = "drbg_pr_ctr_aes192",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_ctr_aes256",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .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)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_hmac_sha256 test */
+ .alg = "drbg_pr_hmac_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_hmac_sha512",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .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)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_sha256 test */
+ .alg = "drbg_pr_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_sha512",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
.alg = "ecb(__aes-aesni)",
.test = alg_test_null,
.fips_allowed = 1,
@@ -2925,6 +3177,38 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}, {
+ .alg = "lz4",
+ .test = alg_test_comp,
+ .fips_allowed = 1,
+ .suite = {
+ .comp = {
+ .comp = {
+ .vecs = lz4_comp_tv_template,
+ .count = LZ4_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = lz4_decomp_tv_template,
+ .count = LZ4_DECOMP_TEST_VECTORS
+ }
+ }
+ }
+ }, {
+ .alg = "lz4hc",
+ .test = alg_test_comp,
+ .fips_allowed = 1,
+ .suite = {
+ .comp = {
+ .comp = {
+ .vecs = lz4hc_comp_tv_template,
+ .count = LZ4HC_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = lz4hc_decomp_tv_template,
+ .count = LZ4HC_DECOMP_TEST_VECTORS
+ }
+ }
+ }
+ }, {
.alg = "lzo",
.test = alg_test_comp,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 69d0dd8ef27e..62e2485bb428 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -32,7 +32,7 @@
#define MAX_DIGEST_SIZE 64
#define MAX_TAP 8
-#define MAX_KEYLEN 56
+#define MAX_KEYLEN 160
#define MAX_IVLEN 32
struct hash_testvec {
@@ -92,6 +92,21 @@ struct cprng_testvec {
unsigned short loops;
};
+struct drbg_testvec {
+ unsigned char *entropy;
+ size_t entropylen;
+ unsigned char *entpra;
+ unsigned char *entprb;
+ size_t entprlen;
+ unsigned char *addtla;
+ unsigned char *addtlb;
+ size_t addtllen;
+ unsigned char *pers;
+ size_t perslen;
+ unsigned char *expected;
+ size_t expectedlen;
+};
+
static char zeroed_string[48];
/*
@@ -1807,18 +1822,59 @@ static struct hash_testvec tgr128_tv_template[] = {
},
};
-#define GHASH_TEST_VECTORS 1
+#define GHASH_TEST_VECTORS 5
static struct hash_testvec ghash_tv_template[] =
{
{
-
- .key = "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03\xff\xca\xff\x95\xf8\x30\xf0\x61",
+ .key = "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03"
+ "\xff\xca\xff\x95\xf8\x30\xf0\x61",
.ksize = 16,
- .plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+ .plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+ "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
.psize = 16,
.digest = "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
"\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+ }, {
+ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ksize = 16,
+ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+ .digest = "\x3e\x1f\x5c\x4d\x65\xf0\xef\xce"
+ "\x0d\x61\x06\x27\x66\x51\xd5\xe2",
+ .np = 2,
+ .tap = {14, 14}
+ }, {
+ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ .ksize = 16,
+ .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ .psize = 50,
+ .digest = "\xfb\x49\x8a\x36\xe1\x96\xe1\x96"
+ "\xe1\x96\xe1\x96\xe1\x96\xe1\x96",
+ }, {
+ .key = "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
+ "\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+ .ksize = 16,
+ .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ .psize = 50,
+ .digest = "\x2b\x5c\x0c\x7f\x52\xd1\x60\xc2"
+ "\x49\xed\x6e\x32\x7a\xa9\xbe\x08",
+ }, {
+ .key = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+ "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+ .ksize = 16,
+ .plaintext = "Test With Truncation",
+ .psize = 20,
+ .digest = "\xf8\x94\x87\x2a\x4b\x63\x99\x28"
+ "\x23\xf7\x93\xf7\x19\xf5\x96\xd9",
},
};
@@ -3097,8 +3153,8 @@ static struct cipher_testvec des_enc_tv_template[] = {
"\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3207,8 +3263,8 @@ static struct cipher_testvec des_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3333,8 +3389,8 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
"\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3442,8 +3498,8 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3517,8 +3573,8 @@ static struct cipher_testvec des_ctr_enc_tv_template[] = {
"\x69\x74\xA1\x06\x46\x0F\x4E\x75",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
.klen = 8,
@@ -3663,8 +3719,8 @@ static struct cipher_testvec des_ctr_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
.klen = 8,
@@ -3899,8 +3955,8 @@ static struct cipher_testvec des3_ede_enc_tv_template[] = {
"\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4064,8 +4120,8 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4244,8 +4300,8 @@ static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = {
"\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4424,8 +4480,8 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4564,8 +4620,8 @@ static struct cipher_testvec des3_ede_ctr_enc_tv_template[] = {
"\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
"\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -4842,8 +4898,8 @@ static struct cipher_testvec des3_ede_ctr_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
"\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -5182,8 +5238,8 @@ static struct cipher_testvec bf_enc_tv_template[] = {
"\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5374,8 +5430,8 @@ static struct cipher_testvec bf_dec_tv_template[] = {
"\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5531,8 +5587,8 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
"\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5688,8 +5744,8 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
"\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -6694,8 +6750,8 @@ static struct cipher_testvec tf_enc_tv_template[] = {
"\x2C\x75\x64\xC4\xCA\xC1\x7E\xD5",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -6862,8 +6918,8 @@ static struct cipher_testvec tf_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -7045,8 +7101,8 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
"\x0A\xA3\x30\x10\x26\x25\x41\x2C",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -7228,8 +7284,8 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -8302,8 +8358,8 @@ static struct cipher_testvec tf_lrw_enc_tv_template[] = {
"\x11\xd7\xb8\x6e\xea\xe1\x80\x30",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -8555,8 +8611,8 @@ static struct cipher_testvec tf_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -8897,8 +8953,8 @@ static struct cipher_testvec tf_xts_enc_tv_template[] = {
"\x37\x30\xe1\x91\x8d\xb3\x2a\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -9240,8 +9296,8 @@ static struct cipher_testvec tf_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -9438,8 +9494,8 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
"\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9664,8 +9720,8 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9846,8 +9902,8 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
"\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9987,8 +10043,8 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -11061,8 +11117,8 @@ static struct cipher_testvec serpent_lrw_enc_tv_template[] = {
"\xd9\x51\x0f\xd7\x94\x2f\xc5\xa7",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11314,8 +11370,8 @@ static struct cipher_testvec serpent_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11656,8 +11712,8 @@ static struct cipher_testvec serpent_xts_enc_tv_template[] = {
"\xd4\xa0\x91\x98\x11\x5f\x4d\xb1",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11999,8 +12055,8 @@ static struct cipher_testvec serpent_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -12182,8 +12238,8 @@ static struct cipher_testvec cast6_enc_tv_template[] = {
"\x11\x74\x93\x57\xB4\x7E\xC6\x00",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12353,8 +12409,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12494,8 +12550,8 @@ static struct cipher_testvec cast6_cbc_enc_tv_template[] = {
"\x22\x46\x89\x2D\x0F\x2B\x08\x24",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12635,8 +12691,8 @@ static struct cipher_testvec cast6_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12792,8 +12848,8 @@ static struct cipher_testvec cast6_ctr_enc_tv_template[] = {
"\xF9\xC5\xDD\x27\xB3\x39\xCB\xCB",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12949,8 +13005,8 @@ static struct cipher_testvec cast6_ctr_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -13096,8 +13152,8 @@ static struct cipher_testvec cast6_lrw_enc_tv_template[] = {
"\xC4\xF5\x99\x61\xBC\xBB\x5B\x46",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13243,8 +13299,8 @@ static struct cipher_testvec cast6_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13392,8 +13448,8 @@ static struct cipher_testvec cast6_xts_enc_tv_template[] = {
"\x22\x60\x4E\xE8\xA4\x5D\x85\xB9",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13541,8 +13597,8 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13749,8 +13805,8 @@ static struct cipher_testvec aes_enc_tv_template[] = {
"\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -13921,8 +13977,8 @@ static struct cipher_testvec aes_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -14140,8 +14196,8 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
"\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -14359,8 +14415,8 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -16265,8 +16321,8 @@ static struct cipher_testvec aes_lrw_enc_tv_template[] = {
"\x74\x3f\x7d\x58\x88\x75\xde\x3e",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -16519,8 +16575,8 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -16861,8 +16917,8 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
"\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -17203,8 +17259,8 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -17420,8 +17476,8 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
"\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
"\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -17775,8 +17831,8 @@ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
"\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -20743,6 +20799,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
@@ -20907,8 +21791,8 @@ static struct cipher_testvec cast5_enc_tv_template[] = {
"\xF5\xBC\x25\xD6\x02\x56\x57\x1C",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21068,8 +21952,8 @@ static struct cipher_testvec cast5_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21206,8 +22090,8 @@ static struct cipher_testvec cast5_cbc_enc_tv_template[] = {
"\x1D\x18\x66\x44\x5B\x8F\x14\xEB",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21344,8 +22228,8 @@ static struct cipher_testvec cast5_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21495,8 +22379,8 @@ static struct cipher_testvec cast5_ctr_enc_tv_template[] = {
"\xC0\x0D\x96\xAA\x23\xF8\xFE\x13",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21646,8 +22530,8 @@ static struct cipher_testvec cast5_ctr_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -22805,8 +23689,8 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
"\x33\x1A\xBB\xD3\xA2\x7E\x97\x66",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23105,8 +23989,8 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
"\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23401,8 +24285,8 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
"\x70\xC5\xB9\x0B\x3B\x7A\x6E\x6C",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23697,8 +24581,8 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
"\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -25283,8 +26167,8 @@ static struct cipher_testvec camellia_lrw_enc_tv_template[] = {
"\x5a\xa8\x92\x7f\xba\xe6\x0c\x95",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -25536,8 +26420,8 @@ static struct cipher_testvec camellia_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -25878,8 +26762,8 @@ static struct cipher_testvec camellia_xts_enc_tv_template[] = {
"\xd5\xc6\x99\xcc\x4e\x6c\x94\x95",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -26221,8 +27105,8 @@ static struct cipher_testvec camellia_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -28589,4 +29473,70 @@ static struct hash_testvec bfin_crc_tv_template[] = {
};
+#define LZ4_COMP_TEST_VECTORS 1
+#define LZ4_DECOMP_TEST_VECTORS 1
+
+static struct comp_testvec lz4_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 45,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ },
+};
+
+static struct comp_testvec lz4_decomp_tv_template[] = {
+ {
+ .inlen = 45,
+ .outlen = 70,
+ .input = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
+#define LZ4HC_COMP_TEST_VECTORS 1
+#define LZ4HC_DECOMP_TEST_VECTORS 1
+
+static struct comp_testvec lz4hc_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 45,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ },
+};
+
+static struct comp_testvec lz4hc_decomp_tv_template[] = {
+ {
+ .inlen = 45,
+ .outlen = 70,
+ .input = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
#endif /* _CRYPTO_TESTMGR_H */
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 06b62e5cdcc7..c9ee681d57fd 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -168,7 +168,7 @@ static int zlib_compress_update(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -198,7 +198,7 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -283,7 +283,7 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -331,7 +331,7 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;