diff options
Diffstat (limited to 'crypto')
41 files changed, 1008 insertions, 470 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index 3d056e7d..8c588ed3 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -61,7 +61,6 @@ config CRYPTO_BLKCIPHER2 tristate select CRYPTO_ALGAPI2 select CRYPTO_RNG2 - select CRYPTO_WORKQUEUE config CRYPTO_HASH tristate @@ -137,10 +136,11 @@ config CRYPTO_USER Userspace configuration for cryptographic instantiations such as cbc(aes). +if CRYPTO_MANAGER2 + config CRYPTO_MANAGER_DISABLE_TESTS bool "Disable run-time self tests" default y - depends on CRYPTO_MANAGER2 help Disable run-time self tests that normally take place at algorithm registration. @@ -155,14 +155,10 @@ config CRYPTO_MANAGER_EXTRA_TESTS This is intended for developer use only, as these tests take much longer to run than the normal self tests. +endif # if CRYPTO_MANAGER2 + config CRYPTO_GF128MUL - tristate "GF(2^128) multiplication functions" - help - Efficient table driven implementation of multiplications in the - field GF(2^128). This is needed by some cypher modes. This - option will be selected automatically if you select such a - cipher mode. Only select this option by hand if you expect to load - an external module that requires these functions. + tristate config CRYPTO_NULL tristate "Null algorithms" @@ -186,15 +182,11 @@ config CRYPTO_PCRYPT This converts an arbitrary crypto algorithm into a parallel algorithm that executes in kernel threads. -config CRYPTO_WORKQUEUE - tristate - config CRYPTO_CRYPTD tristate "Software async crypto daemon" select CRYPTO_BLKCIPHER select CRYPTO_HASH select CRYPTO_MANAGER - select CRYPTO_WORKQUEUE help This is a generic software asynchronous crypto daemon that converts an arbitrary synchronous software crypto algorithm @@ -279,6 +271,7 @@ config CRYPTO_CCM select CRYPTO_CTR select CRYPTO_HASH select CRYPTO_AEAD + select CRYPTO_MANAGER help Support for Counter with CBC MAC. Required for IPsec. @@ -288,6 +281,7 @@ config CRYPTO_GCM select CRYPTO_AEAD select CRYPTO_GHASH select CRYPTO_NULL + select CRYPTO_MANAGER help Support for Galois/Counter Mode (GCM) and Galois Message Authentication Code (GMAC). Required for IPSec. @@ -297,6 +291,7 @@ config CRYPTO_CHACHA20POLY1305 select CRYPTO_CHACHA20 select CRYPTO_POLY1305 select CRYPTO_AEAD + select CRYPTO_MANAGER help ChaCha20-Poly1305 AEAD support, RFC7539. @@ -411,6 +406,7 @@ config CRYPTO_SEQIV select CRYPTO_BLKCIPHER select CRYPTO_NULL select CRYPTO_RNG_DEFAULT + select CRYPTO_MANAGER help This IV generator generates an IV based on a sequence number by xoring it with a salt. This algorithm is mainly useful for CTR @@ -420,7 +416,7 @@ config CRYPTO_ECHAINIV select CRYPTO_AEAD select CRYPTO_NULL select CRYPTO_RNG_DEFAULT - default m + select CRYPTO_MANAGER help This IV generator generates an IV based on the encryption of a sequence number xored with a salt. This is the default @@ -456,6 +452,7 @@ config CRYPTO_CTR config CRYPTO_CTS tristate "CTS support" select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER help CTS: Cipher Text Stealing This is the Cipher Text Stealing mode as described by @@ -521,6 +518,7 @@ config CRYPTO_XTS config CRYPTO_KEYWRAP tristate "Key wrapping support" select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER help Support for key wrapping (NIST SP800-38F / RFC3394) without padding. @@ -551,6 +549,7 @@ config CRYPTO_ADIANTUM select CRYPTO_CHACHA20 select CRYPTO_POLY1305 select CRYPTO_NHPOLY1305 + select CRYPTO_MANAGER help Adiantum is a tweakable, length-preserving encryption mode designed for fast and secure disk encryption, especially on @@ -684,6 +683,14 @@ config CRYPTO_CRC32_MIPS instructions, when available. +config CRYPTO_XXHASH + tristate "xxHash hash algorithm" + select CRYPTO_HASH + select XXHASH + help + xxHash non-cryptographic hash algorithm. Extremely fast, working at + speeds close to RAM limits. + config CRYPTO_CRCT10DIF tristate "CRCT10DIF algorithm" select CRYPTO_HASH diff --git a/crypto/Makefile b/crypto/Makefile index 266a4cdb..9479e1a4 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -6,8 +6,6 @@ obj-$(CONFIG_CRYPTO) += crypto.o crypto-y := api.o cipher.o compress.o memneq.o -obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o - obj-$(CONFIG_CRYPTO_ENGINE) += crypto_engine.o obj-$(CONFIG_CRYPTO_FIPS) += fips.o @@ -131,6 +129,7 @@ obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o obj-$(CONFIG_CRYPTO_LZ4) += lz4.o obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o +obj-$(CONFIG_CRYPTO_XXHASH) += xxhash_generic.o obj-$(CONFIG_CRYPTO_842) += 842.o obj-$(CONFIG_CRYPTO_RNG2) += rng.o obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o diff --git a/crypto/aead.c b/crypto/aead.c index 4908b5e8..fc1d7ad8 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -89,6 +89,42 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) } EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); +int crypto_aead_encrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct crypto_alg *alg = aead->base.__crt_alg; + unsigned int cryptlen = req->cryptlen; + int ret; + + crypto_stats_get(alg); + if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) + ret = -ENOKEY; + else + ret = crypto_aead_alg(aead)->encrypt(req); + crypto_stats_aead_encrypt(cryptlen, alg, ret); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_aead_encrypt); + +int crypto_aead_decrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct crypto_alg *alg = aead->base.__crt_alg; + unsigned int cryptlen = req->cryptlen; + int ret; + + crypto_stats_get(alg); + if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) + ret = -ENOKEY; + else if (req->cryptlen < crypto_aead_authsize(aead)) + ret = -EINVAL; + else + ret = crypto_aead_alg(aead)->decrypt(req); + crypto_stats_aead_decrypt(cryptlen, alg, ret); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_aead_decrypt); + static void crypto_aead_exit_tfm(struct crypto_tfm *tfm) { struct crypto_aead *aead = __crypto_aead_cast(tfm); diff --git a/crypto/algapi.c b/crypto/algapi.c index 4c9c86b5..5278e139 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -26,23 +26,6 @@ static LIST_HEAD(crypto_template_list); -static inline int crypto_set_driver_name(struct crypto_alg *alg) -{ - static const char suffix[] = "-generic"; - char *driver_name = alg->cra_driver_name; - int len; - - if (*driver_name) - return 0; - - len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); - if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) - return -ENAMETOOLONG; - - memcpy(driver_name + len, suffix, sizeof(suffix)); - return 0; -} - static inline void crypto_check_module_sig(struct module *mod) { if (fips_enabled && mod && !module_sig_ok(mod)) @@ -54,6 +37,9 @@ static int crypto_check_alg(struct crypto_alg *alg) { crypto_check_module_sig(alg->cra_module); + if (!alg->cra_name[0] || !alg->cra_driver_name[0]) + return -EINVAL; + if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; @@ -79,7 +65,7 @@ static int crypto_check_alg(struct crypto_alg *alg) refcount_set(&alg->cra_refcnt, 1); - return crypto_set_driver_name(alg); + return 0; } static void crypto_free_instance(struct crypto_instance *inst) @@ -952,19 +938,6 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) } EXPORT_SYMBOL_GPL(crypto_dequeue_request); -int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm) -{ - struct crypto_async_request *req; - - list_for_each_entry(req, &queue->list, list) { - if (req->tfm == tfm) - return 1; - } - - return 0; -} -EXPORT_SYMBOL_GPL(crypto_tfm_in_queue); - static inline void crypto_inc_byte(u8 *a, unsigned int size) { u8 *b = (a + size); diff --git a/crypto/anubis.c b/crypto/anubis.c index 673927de..f9ce78fd 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -673,6 +673,7 @@ static void anubis_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) static struct crypto_alg anubis_alg = { .cra_name = "anubis", + .cra_driver_name = "anubis-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = ANUBIS_BLOCK_SIZE, .cra_ctxsize = sizeof (struct anubis_ctx), diff --git a/crypto/arc4.c b/crypto/arc4.c index 2233d364..b78dcb39 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -115,6 +115,7 @@ static int ecb_arc4_crypt(struct skcipher_request *req) static struct crypto_alg arc4_cipher = { .cra_name = "arc4", + .cra_driver_name = "arc4-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = ARC4_BLOCK_SIZE, .cra_ctxsize = sizeof(struct arc4_ctx), @@ -132,6 +133,7 @@ static struct crypto_alg arc4_cipher = { static struct skcipher_alg arc4_skcipher = { .base.cra_name = "ecb(arc4)", + .base.cra_driver_name = "ecb(arc4)-generic", .base.cra_priority = 100, .base.cra_blocksize = ARC4_BLOCK_SIZE, .base.cra_ctxsize = sizeof(struct arc4_ctx), diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index e38a2d61..76c13dab 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -65,6 +65,8 @@ struct chachapoly_req_ctx { unsigned int cryptlen; /* Actual AD, excluding IV */ unsigned int assoclen; + /* request flags, with MAY_SLEEP cleared if needed */ + u32 flags; union { struct poly_req poly; struct chacha_req chacha; @@ -74,8 +76,12 @@ struct chachapoly_req_ctx { static inline void async_done_continue(struct aead_request *req, int err, int (*cont)(struct aead_request *)) { - if (!err) + if (!err) { + struct chachapoly_req_ctx *rctx = aead_request_ctx(req); + + rctx->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; err = cont(req); + } if (err != -EINPROGRESS && err != -EBUSY) aead_request_complete(req, err); @@ -133,16 +139,12 @@ static int chacha_decrypt(struct aead_request *req) chacha_iv(creq->iv, req, 1); - sg_init_table(rctx->src, 2); src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); dst = src; - - if (req->src != req->dst) { - sg_init_table(rctx->dst, 2); + if (req->src != req->dst) dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); - } - skcipher_request_set_callback(&creq->req, aead_request_flags(req), + skcipher_request_set_callback(&creq->req, rctx->flags, chacha_decrypt_done, req); skcipher_request_set_tfm(&creq->req, ctx->chacha); skcipher_request_set_crypt(&creq->req, src, dst, @@ -176,17 +178,13 @@ static int poly_tail(struct aead_request *req) struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; - __le64 len; int err; - sg_init_table(preq->src, 1); - len = cpu_to_le64(rctx->assoclen); - memcpy(&preq->tail.assoclen, &len, sizeof(len)); - len = cpu_to_le64(rctx->cryptlen); - memcpy(&preq->tail.cryptlen, &len, sizeof(len)); - sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail)); + preq->tail.assoclen = cpu_to_le64(rctx->assoclen); + preq->tail.cryptlen = cpu_to_le64(rctx->cryptlen); + sg_init_one(preq->src, &preq->tail, sizeof(preq->tail)); - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_tail_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, preq->src, @@ -209,15 +207,14 @@ static int poly_cipherpad(struct aead_request *req) struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; - unsigned int padlen, bs = POLY1305_BLOCK_SIZE; + unsigned int padlen; int err; - padlen = (bs - (rctx->cryptlen % bs)) % bs; + padlen = -rctx->cryptlen % POLY1305_BLOCK_SIZE; memset(preq->pad, 0, sizeof(preq->pad)); - sg_init_table(preq->src, 1); - sg_set_buf(preq->src, &preq->pad, padlen); + sg_init_one(preq->src, preq->pad, padlen); - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_cipherpad_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); @@ -245,10 +242,9 @@ static int poly_cipher(struct aead_request *req) if (rctx->cryptlen == req->cryptlen) /* encrypting */ crypt = req->dst; - sg_init_table(rctx->src, 2); crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen); - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_cipher_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); @@ -270,15 +266,14 @@ static int poly_adpad(struct aead_request *req) struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; - unsigned int padlen, bs = POLY1305_BLOCK_SIZE; + unsigned int padlen; int err; - padlen = (bs - (rctx->assoclen % bs)) % bs; + padlen = -rctx->assoclen % POLY1305_BLOCK_SIZE; memset(preq->pad, 0, sizeof(preq->pad)); - sg_init_table(preq->src, 1); - sg_set_buf(preq->src, preq->pad, padlen); + sg_init_one(preq->src, preq->pad, padlen); - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_adpad_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); @@ -302,7 +297,7 @@ static int poly_ad(struct aead_request *req) struct poly_req *preq = &rctx->u.poly; int err; - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_ad_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); @@ -326,10 +321,9 @@ static int poly_setkey(struct aead_request *req) struct poly_req *preq = &rctx->u.poly; int err; - sg_init_table(preq->src, 1); - sg_set_buf(preq->src, rctx->key, sizeof(rctx->key)); + sg_init_one(preq->src, rctx->key, sizeof(rctx->key)); - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_setkey_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); @@ -353,7 +347,7 @@ static int poly_init(struct aead_request *req) struct poly_req *preq = &rctx->u.poly; int err; - ahash_request_set_callback(&preq->req, aead_request_flags(req), + ahash_request_set_callback(&preq->req, rctx->flags, poly_init_done, req); ahash_request_set_tfm(&preq->req, ctx->poly); @@ -385,13 +379,12 @@ static int poly_genkey(struct aead_request *req) rctx->assoclen -= 8; } - sg_init_table(creq->src, 1); memset(rctx->key, 0, sizeof(rctx->key)); - sg_set_buf(creq->src, rctx->key, sizeof(rctx->key)); + sg_init_one(creq->src, rctx->key, sizeof(rctx->key)); chacha_iv(creq->iv, req, 0); - skcipher_request_set_callback(&creq->req, aead_request_flags(req), + skcipher_request_set_callback(&creq->req, rctx->flags, poly_genkey_done, req); skcipher_request_set_tfm(&creq->req, ctx->chacha); skcipher_request_set_crypt(&creq->req, creq->src, creq->src, @@ -422,16 +415,12 @@ static int chacha_encrypt(struct aead_request *req) chacha_iv(creq->iv, req, 1); - sg_init_table(rctx->src, 2); src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); dst = src; - - if (req->src != req->dst) { - sg_init_table(rctx->dst, 2); + if (req->src != req->dst) dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); - } - skcipher_request_set_callback(&creq->req, aead_request_flags(req), + skcipher_request_set_callback(&creq->req, rctx->flags, chacha_encrypt_done, req); skcipher_request_set_tfm(&creq->req, ctx->chacha); skcipher_request_set_crypt(&creq->req, src, dst, @@ -449,6 +438,7 @@ static int chachapoly_encrypt(struct aead_request *req) struct chachapoly_req_ctx *rctx = aead_request_ctx(req); rctx->cryptlen = req->cryptlen; + rctx->flags = aead_request_flags(req); /* encrypt call chain: * - chacha_encrypt/done() @@ -470,6 +460,7 @@ static int chachapoly_decrypt(struct aead_request *req) struct chachapoly_req_ctx *rctx = aead_request_ctx(req); rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; + rctx->flags = aead_request_flags(req); /* decrypt call chain: * - poly_genkey/done() diff --git a/crypto/chacha_generic.c b/crypto/chacha_generic.c index d2ec0499..d283bd3b 100644 --- a/crypto/chacha_generic.c +++ b/crypto/chacha_generic.c @@ -36,7 +36,7 @@ static void chacha_docrypt(u32 *state, u8 *dst, const u8 *src, } static int chacha_stream_xor(struct skcipher_request *req, - struct chacha_ctx *ctx, u8 *iv) + const struct chacha_ctx *ctx, const u8 *iv) { struct skcipher_walk walk; u32 state[16]; @@ -60,7 +60,7 @@ static int chacha_stream_xor(struct skcipher_request *req, return err; } -void crypto_chacha_init(u32 *state, struct chacha_ctx *ctx, u8 *iv) +void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv) { state[0] = 0x61707865; /* "expa" */ state[1] = 0x3320646e; /* "nd 3" */ diff --git a/crypto/cryptd.c b/crypto/cryptd.c index b3bb9939..c34d1030 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -21,7 +21,6 @@ #include <crypto/internal/aead.h> #include <crypto/internal/skcipher.h> #include <crypto/cryptd.h> -#include <crypto/crypto_wq.h> #include <linux/atomic.h> #include <linux/err.h> #include <linux/init.h> @@ -31,11 +30,14 @@ #include <linux/scatterlist.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/workqueue.h> static unsigned int cryptd_max_cpu_qlen = 1000; module_param(cryptd_max_cpu_qlen, uint, 0); MODULE_PARM_DESC(cryptd_max_cpu_qlen, "Set cryptd Max queue depth"); +static struct workqueue_struct *cryptd_wq; + struct cryptd_cpu_queue { struct crypto_queue queue; struct work_struct work; @@ -141,7 +143,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue, if (err == -ENOSPC) goto out_put_cpu; - queue_work_on(cpu, kcrypto_wq, &cpu_queue->work); + queue_work_on(cpu, cryptd_wq, &cpu_queue->work); if (!atomic_read(refcnt)) goto out_put_cpu; @@ -184,7 +186,7 @@ static void cryptd_queue_worker(struct work_struct *work) req->complete(req, 0); if (cpu_queue->queue.qlen) - queue_work(kcrypto_wq, &cpu_queue->work); + queue_work(cryptd_wq, &cpu_queue->work); } static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm) @@ -923,7 +925,7 @@ static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb) switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_BLKCIPHER: return cryptd_create_skcipher(tmpl, tb, &queue); - case CRYPTO_ALG_TYPE_DIGEST: + case CRYPTO_ALG_TYPE_HASH: return cryptd_create_hash(tmpl, tb, &queue); case CRYPTO_ALG_TYPE_AEAD: return cryptd_create_aead(tmpl, tb, &queue); @@ -1123,19 +1125,31 @@ static int __init cryptd_init(void) { int err; + cryptd_wq = alloc_workqueue("cryptd", WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, + 1); + if (!cryptd_wq) + return -ENOMEM; + err = cryptd_init_queue(&queue, cryptd_max_cpu_qlen); if (err) - return err; + goto err_destroy_wq; err = crypto_register_template(&cryptd_tmpl); if (err) - cryptd_fini_queue(&queue); + goto err_fini_queue; + return 0; + +err_fini_queue: + cryptd_fini_queue(&queue); +err_destroy_wq: + destroy_workqueue(cryptd_wq); return err; } static void __exit cryptd_exit(void) { + destroy_workqueue(cryptd_wq); cryptd_fini_queue(&queue); crypto_unregister_template(&cryptd_tmpl); } diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c index 9320d4ea..6aa9a4c2 100644 --- a/crypto/crypto_null.c +++ b/crypto/crypto_null.c @@ -105,6 +105,7 @@ static struct shash_alg digest_null = { .final = null_final, .base = { .cra_name = "digest_null", + .cra_driver_name = "digest_null-generic", .cra_blocksize = NULL_BLOCK_SIZE, .cra_module = THIS_MODULE, } @@ -127,6 +128,7 @@ static struct skcipher_alg skcipher_null = { static struct crypto_alg null_algs[] = { { .cra_name = "cipher_null", + .cra_driver_name = "cipher_null-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = NULL_BLOCK_SIZE, .cra_ctxsize = 0, @@ -139,6 +141,7 @@ static struct crypto_alg null_algs[] = { { .cia_decrypt = null_crypt } } }, { .cra_name = "compress_null", + .cra_driver_name = "compress_null-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_blocksize = NULL_BLOCK_SIZE, .cra_ctxsize = 0, diff --git a/crypto/crypto_user_base.c b/crypto/crypto_user_base.c index f25d3f32..e48da3b7 100644 --- a/crypto/crypto_user_base.c +++ b/crypto/crypto_user_base.c @@ -465,8 +465,8 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, return err; } - err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX, - crypto_policy, extack); + err = nlmsg_parse_deprecated(nlh, crypto_msg_min[type], attrs, + CRYPTOCFGA_MAX, crypto_policy, extack); if (err < 0) return err; diff --git a/crypto/crypto_wq.c b/crypto/crypto_wq.c deleted file mode 100644 index 2f1b8d12..00000000 --- a/crypto/crypto_wq.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Workqueue for crypto subsystem - * - * Copyright (c) 2009 Intel Corp. - * Author: Huang Ying <ying.huang@intel.com> - * - * 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 <linux/workqueue.h> -#include <linux/module.h> -#include <crypto/algapi.h> -#include <crypto/crypto_wq.h> - -struct workqueue_struct *kcrypto_wq; -EXPORT_SYMBOL_GPL(kcrypto_wq); - -static int __init crypto_wq_init(void) -{ - kcrypto_wq = alloc_workqueue("crypto", - WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1); - if (unlikely(!kcrypto_wq)) - return -ENOMEM; - return 0; -} - -static void __exit crypto_wq_exit(void) -{ - destroy_workqueue(kcrypto_wq); -} - -subsys_initcall(crypto_wq_init); -module_exit(crypto_wq_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Workqueue for crypto subsystem"); diff --git a/crypto/deflate.c b/crypto/deflate.c index aab089cd..1143ccbe 100644 --- a/crypto/deflate.c +++ b/crypto/deflate.c @@ -279,6 +279,7 @@ static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src, static struct crypto_alg alg = { .cra_name = "deflate", + .cra_driver_name = "deflate-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct deflate_ctx), .cra_module = THIS_MODULE, diff --git a/crypto/drbg.c b/crypto/drbg.c index 2a5b16bb..b6929eb5 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -220,6 +220,57 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) } /* + * FIPS 140-2 continuous self test for the noise source + * The test is performed on the noise source input data. Thus, the function + * implicitly knows the size of the buffer to be equal to the security + * strength. + * + * Note, this function disregards the nonce trailing the entropy data during + * initial seeding. + * + * drbg->drbg_mutex must have been taken. + * + * @drbg DRBG handle + * @entropy buffer of seed data to be checked + * + * return: + * 0 on success + * -EAGAIN on when the CTRNG is not yet primed + * < 0 on error + */ +static int drbg_fips_continuous_test(struct drbg_state *drbg, + const unsigned char *entropy) +{ + unsigned short entropylen = drbg_sec_strength(drbg->core->flags); + int ret = 0; + + if (!IS_ENABLED(CONFIG_CRYPTO_FIPS)) + return 0; + + /* skip test if we test the overall system */ + if (list_empty(&drbg->test_data.list)) + return 0; + /* only perform test in FIPS mode */ + if (!fips_enabled) + return 0; + + if (!drbg->fips_primed) { + /* Priming of FIPS test */ + memcpy(drbg->prev, entropy, entropylen); + drbg->fips_primed = true; + /* priming: another round is needed */ + return -EAGAIN; + } + ret = memcmp(drbg->prev, entropy, entropylen); + if (!ret) + panic("DRBG continuous self test failed\n"); + memcpy(drbg->prev, entropy, entropylen); + + /* the test shall pass when the two values are not equal */ + return 0; +} + +/* * Convert an integer into a byte representation of this integer. * The byte representation is big-endian * @@ -998,6 +1049,22 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, return ret; } +static inline int drbg_get_random_bytes(struct drbg_state *drbg, + unsigned char *entropy, + unsigned int entropylen) +{ + int ret; + + do { + get_random_bytes(entropy, entropylen); + ret = drbg_fips_continuous_test(drbg, entropy); + if (ret && ret != -EAGAIN) + return ret; + } while (ret); + + return 0; +} + static void drbg_async_seed(struct work_struct *work) { struct drbg_string data; @@ -1006,16 +1073,20 @@ static void drbg_async_seed(struct work_struct *work) seed_work); unsigned int entropylen = drbg_sec_strength(drbg->core->flags); unsigned char entropy[32]; + int ret; BUG_ON(!entropylen); BUG_ON(entropylen > sizeof(entropy)); - get_random_bytes(entropy, entropylen); drbg_string_fill(&data, entropy, entropylen); list_add_tail(&data.list, &seedlist); mutex_lock(&drbg->drbg_mutex); + ret = drbg_get_random_bytes(drbg, entropy, entropylen); + if (ret) + goto unlock; + /* If nonblocking pool is initialized, deactivate Jitter RNG */ crypto_free_rng(drbg->jent); drbg->jent = NULL; @@ -1030,6 +1101,7 @@ static void drbg_async_seed(struct work_struct *work) if (drbg->seeded) drbg->reseed_threshold = drbg_max_requests(drbg); +unlock: mutex_unlock(&drbg->drbg_mutex); memzero_explicit(entropy, entropylen); @@ -1081,7 +1153,9 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, BUG_ON((entropylen * 2) > sizeof(entropy)); /* Get seed from in-kernel /dev/urandom */ - get_random_bytes(entropy, entropylen); + ret = drbg_get_random_bytes(drbg, entropy, entropylen); + if (ret) + goto out; if (!drbg->jent) { drbg_string_fill(&data1, entropy, entropylen); @@ -1094,7 +1168,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, entropylen); if (ret) { pr_devel("DRBG: jent failed with %d\n", ret); - return ret; + goto out; } drbg_string_fill(&data1, entropy, entropylen * 2); @@ -1121,6 +1195,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, ret = __drbg_seed(drbg, &seedlist, reseed); +out: memzero_explicit(entropy, entropylen * 2); return ret; @@ -1142,6 +1217,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->reseed_ctr = 0; drbg->d_ops = NULL; drbg->core = NULL; + if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { + kzfree(drbg->prev); + drbg->prev = NULL; + drbg->fips_primed = false; + } } /* @@ -1211,6 +1291,14 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1); } + if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { + drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags), + GFP_KERNEL); + if (!drbg->prev) + goto fini; + drbg->fips_primed = false; + } + return 0; fini: diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c index 4e870440..58f93531 100644 --- a/crypto/fcrypt.c +++ b/crypto/fcrypt.c @@ -391,6 +391,7 @@ static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key static struct crypto_alg fcrypt_alg = { .cra_name = "fcrypt", + .cra_driver_name = "fcrypt-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = 8, .cra_ctxsize = sizeof(struct fcrypt_ctx), diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c index e6307935..c8a34779 100644 --- a/crypto/ghash-generic.c +++ b/crypto/ghash-generic.c @@ -34,6 +34,7 @@ static int ghash_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) { struct ghash_ctx *ctx = crypto_shash_ctx(tfm); + be128 k; if (keylen != GHASH_BLOCK_SIZE) { crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); @@ -42,7 +43,12 @@ static int ghash_setkey(struct crypto_shash *tfm, if (ctx->gf128) gf128mul_free_4k(ctx->gf128); - ctx->gf128 = gf128mul_init_4k_lle((be128 *)key); + + BUILD_BUG_ON(sizeof(k) != GHASH_BLOCK_SIZE); + memcpy(&k, key, GHASH_BLOCK_SIZE); /* avoid violating alignment rules */ + ctx->gf128 = gf128mul_init_4k_lle(&k); + memzero_explicit(&k, GHASH_BLOCK_SIZE); + if (!ctx->gf128) return -ENOMEM; diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c index 787dccca..701b8d86 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -56,11 +56,6 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector); * Helper function ***************************************************************************/ -__u64 jent_rol64(__u64 word, unsigned int shift) -{ - return rol64(word, shift); -} - void *jent_zalloc(unsigned int len) { return kzalloc(len, GFP_KERNEL); diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c index acf44b2d..77fa2120 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c @@ -2,7 +2,7 @@ * Non-physical true random number generator based on timing jitter -- * Jitter RNG standalone code. * - * Copyright Stephan Mueller <smueller@chronox.de>, 2015 + * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2019 * * Design * ====== @@ -47,7 +47,7 @@ /* * This Jitterentropy RNG is based on the jitterentropy library - * version 1.1.0 provided at http://www.chronox.de/jent.html + * version 2.1.2 provided at http://www.chronox.de/jent.html */ #ifdef __OPTIMIZE__ @@ -71,10 +71,7 @@ struct rand_data { #define DATA_SIZE_BITS ((sizeof(__u64)) * 8) __u64 last_delta; /* SENSITIVE stuck test */ __s64 last_delta2; /* SENSITIVE stuck test */ - unsigned int stuck:1; /* Time measurement stuck */ unsigned int osr; /* Oversample rate */ - unsigned int stir:1; /* Post-processing stirring */ - unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */ #define JENT_MEMORY_BLOCKS 64 #define JENT_MEMORY_BLOCKSIZE 32 #define JENT_MEMORY_ACCESSLOOPS 128 @@ -89,8 +86,6 @@ struct rand_data { }; /* Flags that can be used to initialize the RNG */ -#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */ -#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */ #define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more * entropy, saves MEMORY_SIZE RAM for * entropy collector */ @@ -99,19 +94,16 @@ struct rand_data { #define JENT_ENOTIME 1 /* Timer service not available */ #define JENT_ECOARSETIME 2 /* Timer too coarse for RNG */ #define JENT_ENOMONOTONIC 3 /* Timer is not monotonic increasing */ -#define JENT_EMINVARIATION 4 /* Timer variations too small for RNG */ #define JENT_EVARVAR 5 /* Timer does not produce variations of * variations (2nd derivation of time is * zero). */ -#define JENT_EMINVARVAR 6 /* Timer variations of variations is tooi - * small. */ +#define JENT_ESTUCK 8 /* Too many stuck results during init. */ /*************************************************************************** * Helper functions ***************************************************************************/ void jent_get_nstime(__u64 *out); -__u64 jent_rol64(__u64 word, unsigned int shift); void *jent_zalloc(unsigned int len); void jent_zfree(void *ptr); int jent_fips_enabled(void); @@ -140,16 +132,16 @@ static __u64 jent_loop_shuffle(struct rand_data *ec, jent_get_nstime(&time); /* - * mix the current state of the random number into the shuffle - * calculation to balance that shuffle a bit more + * Mix the current state of the random number into the shuffle + * calculation to balance that shuffle a bit more. */ if (ec) time ^= ec->data; /* - * we fold the time value as much as possible to ensure that as many - * bits of the time stamp are included as possible + * We fold the time value as much as possible to ensure that as many + * bits of the time stamp are included as possible. */ - for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) { + for (i = 0; ((DATA_SIZE_BITS + bits - 1) / bits) > i; i++) { shuffle ^= time & mask; time = time >> bits; } @@ -169,38 +161,28 @@ static __u64 jent_loop_shuffle(struct rand_data *ec, * CPU Jitter noise source -- this is the noise source based on the CPU * execution time jitter * - * This function folds the time into one bit units by iterating - * through the DATA_SIZE_BITS bit time value as follows: assume our time value - * is 0xabcd - * 1st loop, 1st shift generates 0xd000 - * 1st loop, 2nd shift generates 0x000d - * 2nd loop, 1st shift generates 0xcd00 - * 2nd loop, 2nd shift generates 0x000c - * 3rd loop, 1st shift generates 0xbcd0 - * 3rd loop, 2nd shift generates 0x000b - * 4th loop, 1st shift generates 0xabcd - * 4th loop, 2nd shift generates 0x000a - * Now, the values at the end of the 2nd shifts are XORed together. + * This function injects the individual bits of the time value into the + * entropy pool using an LFSR. * - * The code is deliberately inefficient and shall stay that way. This function - * is the root cause why the code shall be compiled without optimization. This - * function not only acts as folding operation, but this function's execution - * is used to measure the CPU execution time jitter. Any change to the loop in - * this function implies that careful retesting must be done. + * The code is deliberately inefficient with respect to the bit shifting + * and shall stay that way. This function is the root cause why the code + * shall be compiled without optimization. This function not only acts as + * folding operation, but this function's execution is used to measure + * the CPU execution time jitter. Any change to the loop in this function + * implies that careful retesting must be done. * * Input: * @ec entropy collector struct -- may be NULL - * @time time stamp to be folded + * @time time stamp to be injected * @loop_cnt if a value not equal to 0 is set, use the given value as number of * loops to perform the folding * * Output: - * @folded result of folding operation + * updated ec->data * * @return Number of loops the folding operation is performed */ -static __u64 jent_fold_time(struct rand_data *ec, __u64 time, - __u64 *folded, __u64 loop_cnt) +static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt) { unsigned int i; __u64 j = 0; @@ -217,15 +199,34 @@ static __u64 jent_fold_time(struct rand_data *ec, __u64 time, if (loop_cnt) fold_loop_cnt = loop_cnt; for (j = 0; j < fold_loop_cnt; j++) { - new = 0; + new = ec->data; for (i = 1; (DATA_SIZE_BITS) >= i; i++) { __u64 tmp = time << (DATA_SIZE_BITS - i); tmp = tmp >> (DATA_SIZE_BITS - 1); + + /* + * Fibonacci LSFR with polynomial of + * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is + * primitive according to + * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf + * (the shift values are the polynomial values minus one + * due to counting bits from 0 to 63). As the current + * position is always the LSB, the polynomial only needs + * to shift data in from the left without wrap. + */ + tmp ^= ((new >> 63) & 1); + tmp ^= ((new >> 60) & 1); + tmp ^= ((new >> 55) & 1); + tmp ^= ((new >> 30) & 1); + tmp ^= ((new >> 27) & 1); + tmp ^= ((new >> 22) & 1); + new <<= 1; new ^= tmp; } } - *folded = new; + ec->data = new; + return fold_loop_cnt; } @@ -258,7 +259,6 @@ static __u64 jent_fold_time(struct rand_data *ec, __u64 time, */ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt) { - unsigned char *tmpval = NULL; unsigned int wrap = 0; __u64 i = 0; #define MAX_ACC_LOOP_BIT 7 @@ -278,7 +278,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt) acc_loop_cnt = loop_cnt; for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) { - tmpval = ec->mem + ec->memlocation; + unsigned char *tmpval = ec->mem + ec->memlocation; /* * memory access: just add 1 to one byte, * wrap at 255 -- memory access implies read @@ -316,7 +316,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt) * 0 jitter measurement not stuck (good bit) * 1 jitter measurement stuck (reject bit) */ -static void jent_stuck(struct rand_data *ec, __u64 current_delta) +static int jent_stuck(struct rand_data *ec, __u64 current_delta) { __s64 delta2 = ec->last_delta - current_delta; __s64 delta3 = delta2 - ec->last_delta2; @@ -325,14 +325,15 @@ static void jent_stuck(struct rand_data *ec, __u64 current_delta) ec->last_delta2 = delta2; if (!current_delta || !delta2 || !delta3) - ec->stuck = 1; + return 1; + + return 0; } /** * This is the heart of the entropy generation: calculate time deltas and - * use the CPU jitter in the time deltas. The jitter is folded into one - * bit. You can call this function the "random bit generator" as it - * produces one random bit per invocation. + * use the CPU jitter in the time deltas. The jitter is injected into the + * entropy pool. * * WARNING: ensure that ->prev_time is primed before using the output * of this function! This can be done by calling this function @@ -341,12 +342,11 @@ static void jent_stuck(struct rand_data *ec, __u64 current_delta) * Input: * @entropy_collector Reference to entropy collector * - * @return One random bit + * @return result of stuck test */ -static __u64 jent_measure_jitter(struct rand_data *ec) +static int jent_measure_jitter(struct rand_data *ec) { __u64 time = 0; - __u64 data = 0; __u64 current_delta = 0; /* Invoke one noise source before time measurement to add variations */ @@ -360,109 +360,11 @@ static __u64 jent_measure_jitter(struct rand_data *ec) current_delta = time - ec->prev_time; ec->prev_time = time; - /* Now call the next noise sources which also folds the data */ - jent_fold_time(ec, current_delta, &data, 0); - - /* - * Check whether we have a stuck measurement. The enforcement - * is performed after the stuck value has been mixed into the - * entropy pool. - */ - jent_stuck(ec, current_delta); - - return data; -} - -/** - * Von Neuman unbias as explained in RFC 4086 section 4.2. As shown in the - * documentation of that RNG, the bits from jent_measure_jitter are considered - * independent which implies that the Von Neuman unbias operation is applicable. - * A proof of the Von-Neumann unbias operation to remove skews is given in the - * document "A proposal for: Functionality classes for random number - * generators", version 2.0 by Werner Schindler, section 5.4.1. - * - * Input: - * @entropy_collector Reference to entropy collector - * - * @return One random bit - */ -static __u64 jent_unbiased_bit(struct rand_data *entropy_collector) -{ - do { - __u64 a = jent_measure_jitter(entropy_collector); - __u64 b = jent_measure_jitter(entropy_collector); - - if (a == b) - continue; - if (1 == a) - return 1; - else - return 0; - } while (1); -} - -/** - * Shuffle the pool a bit by mixing some value with a bijective function (XOR) - * into the pool. - * - * The function generates a mixer value that depends on the bits set and the - * location of the set bits in the random number generated by the entropy - * source. Therefore, based on the generated random number, this mixer value - * can have 2**64 different values. That mixer value is initialized with the - * first two SHA-1 constants. After obtaining the mixer value, it is XORed into - * the random number. - * - * The mixer value is not assumed to contain any entropy. But due to the XOR - * operation, it can also not destroy any entropy present in the entropy pool. - * - * Input: - * @entropy_collector Reference to entropy collector - */ -static void jent_stir_pool(struct rand_data *entropy_collector) -{ - /* - * to shut up GCC on 32 bit, we have to initialize the 64 variable - * with two 32 bit variables - */ - union c { - __u64 u64; - __u32 u32[2]; - }; - /* - * This constant is derived from the first two 32 bit initialization - * vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1 - */ - union c constant; - /* - * The start value of the mixer variable is derived from the third - * and fourth 32 bit initialization vector of SHA-1 as defined in - * FIPS 180-4 section 5.3.1 - */ - union c mixer; - unsigned int i = 0; - - /* - * Store the SHA-1 constants in reverse order to make up the 64 bit - * value -- this applies to a little endian system, on a big endian - * system, it reverses as expected. But this really does not matter - * as we do not rely on the specific numbers. We just pick the SHA-1 - * constants as they have a good mix of bit set and unset. - */ - constant.u32[1] = 0x67452301; - constant.u32[0] = 0xefcdab89; - mixer.u32[1] = 0x98badcfe; - mixer.u32[0] = 0x10325476; + /* Now call the next noise sources which also injects the data */ + jent_lfsr_time(ec, current_delta, 0); - for (i = 0; i < DATA_SIZE_BITS; i++) { - /* - * get the i-th bit of the input random number and only XOR - * the constant into the mixer value when that bit is set - */ - if ((entropy_collector->data >> i) & 1) - mixer.u64 ^= constant.u64; - mixer.u64 = jent_rol64(mixer.u64, 1); - } - entropy_collector->data ^= mixer.u64; + /* Check whether we have a stuck measurement. */ + return jent_stuck(ec, current_delta); } /** @@ -480,48 +382,9 @@ static void jent_gen_entropy(struct rand_data *ec) jent_measure_jitter(ec); while (1) { - __u64 data = 0; - - if (ec->disable_unbias == 1) - data = jent_measure_jitter(ec); - else - data = jent_unbiased_bit(ec); - - /* enforcement of the jent_stuck test */ - if (ec->stuck) { - /* - * We only mix in the bit considered not appropriate - * without the LSFR. The reason is that if we apply - * the LSFR and we do not rotate, the 2nd bit with LSFR - * will cancel out the first LSFR application on the - * bad bit. - * - * And we do not rotate as we apply the next bit to the - * current bit location again. - */ - ec->data ^= data; - ec->stuck = 0; + /* If a stuck measurement is received, repeat measurement */ + if (jent_measure_jitter(ec)) continue; - } - - /* - * Fibonacci LSFR with polynom of - * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is - * primitive according to - * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf - * (the shift values are the polynom values minus one - * due to counting bits from 0 to 63). As the current - * position is always the LSB, the polynom only needs - * to shift data in from the left without wrap. - */ - ec->data ^= data; - ec->data ^= ((ec->data >> 63) & 1); - ec->data ^= ((ec->data >> 60) & 1); - ec->data ^= ((ec->data >> 55) & 1); - ec->data ^= ((ec->data >> 30) & 1); - ec->data ^= ((ec->data >> 27) & 1); - ec->data ^= ((ec->data >> 22) & 1); - ec->data = jent_rol64(ec->data, 1); /* * We multiply the loop value with ->osr to obtain the @@ -530,8 +393,6 @@ static void jent_gen_entropy(struct rand_data *ec) if (++k >= (DATA_SIZE_BITS * ec->osr)) break; } - if (ec->stir) - jent_stir_pool(ec); } /** @@ -639,12 +500,6 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr, osr = 1; /* minimum sampling rate is 1 */ entropy_collector->osr = osr; - entropy_collector->stir = 1; - if (flags & JENT_DISABLE_STIR) - entropy_collector->stir = 0; - if (flags & JENT_DISABLE_UNBIAS) - entropy_collector->disable_unbias = 1; - /* fill the data pad with non-zero values */ jent_gen_entropy(entropy_collector); @@ -656,7 +511,6 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector) jent_zfree(entropy_collector->mem); entropy_collector->mem = NULL; jent_zfree(entropy_collector); - entropy_collector = NULL; } int jent_entropy_init(void) @@ -665,8 +519,9 @@ int jent_entropy_init(void) __u64 delta_sum = 0; __u64 old_delta = 0; int time_backwards = 0; - int count_var = 0; int count_mod = 0; + int count_stuck = 0; + struct rand_data ec = { 0 }; /* We could perform statistical tests here, but the problem is * that we only have a few loop counts to do testing. These @@ -695,12 +550,14 @@ int jent_entropy_init(void) for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) { __u64 time = 0; __u64 time2 = 0; - __u64 folded = 0; __u64 delta = 0; unsigned int lowdelta = 0; + int stuck; + /* Invoke core entropy collection logic */ jent_get_nstime(&time); - jent_fold_time(NULL, time, &folded, 1<<MIN_FOLD_LOOP_BIT); + ec.prev_time = time; + jent_lfsr_time(&ec, time, 0); jent_get_nstime(&time2); /* test whether timer works */ @@ -715,6 +572,8 @@ int jent_entropy_init(void) if (!delta) return JENT_ECOARSETIME; + stuck = jent_stuck(&ec, delta); + /* * up to here we did not modify any variable that will be * evaluated later, but we already performed some work. Thus we @@ -725,14 +584,14 @@ int jent_entropy_init(void) if (CLEARCACHE > i) continue; + if (stuck) + count_stuck++; + /* test whether we have an increasing timer */ if (!(time2 > time)) time_backwards++; - /* - * Avoid modulo of 64 bit integer to allow code to compile - * on 32 bit architectures. - */ + /* use 32 bit value to ensure compilation on 32 bit arches */ lowdelta = time2 - time; if (!(lowdelta % 100)) count_mod++; @@ -743,14 +602,10 @@ int jent_entropy_init(void) * only after the first loop is executed as we need to prime * the old_data value */ - if (i) { - if (delta != old_delta) - count_var++; - if (delta > old_delta) - delta_sum += (delta - old_delta); - else - delta_sum += (old_delta - delta); - } + if (delta > old_delta) + delta_sum += (delta - old_delta); + else + delta_sum += (old_delta - delta); old_delta = delta; } @@ -763,25 +618,29 @@ int jent_entropy_init(void) */ if (3 < time_backwards) return JENT_ENOMONOTONIC; - /* Error if the time variances are always identical */ - if (!delta_sum) - return JENT_EVARVAR; /* * Variations of deltas of time must on average be larger * than 1 to ensure the entropy estimation * implied with 1 is preserved */ - if (delta_sum <= 1) - return JENT_EMINVARVAR; + if ((delta_sum) <= 1) + return JENT_EVARVAR; /* * Ensure that we have variations in the time stamp below 10 for at - * least 10% of all checks -- on some platforms, the counter - * increments in multiples of 100, but not always + * least 10% of all checks -- on some platforms, the counter increments + * in multiples of 100, but not always */ if ((TESTLOOPCOUNT/10 * 9) < count_mod) return JENT_ECOARSETIME; + /* + * If we have more than 90% stuck results, then this Jitter RNG is + * likely to not work well. + */ + if ((TESTLOOPCOUNT/10 * 9) < count_stuck) + return JENT_ESTUCK; + return 0; } diff --git a/crypto/khazad.c b/crypto/khazad.c index b50aa8a3..14ca7f16 100644 --- a/crypto/khazad.c +++ b/crypto/khazad.c @@ -848,6 +848,7 @@ static void khazad_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) static struct crypto_alg khazad_alg = { .cra_name = "khazad", + .cra_driver_name = "khazad-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = KHAZAD_BLOCK_SIZE, .cra_ctxsize = sizeof (struct khazad_ctx), diff --git a/crypto/lrw.c b/crypto/lrw.c index 0cc689ab..b43ea285 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -214,8 +214,12 @@ static void crypt_done(struct crypto_async_request *areq, int err) { struct skcipher_request *req = areq->data; - if (!err) + if (!err) { + struct rctx *rctx = skcipher_request_ctx(req); + + rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; err = xor_tweak_post(req); + } skcipher_request_complete(req, err); } @@ -384,7 +388,7 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE; inst->alg.base.cra_alignmask = alg->base.cra_alignmask | - (__alignof__(__be32) - 1); + (__alignof__(be128) - 1); inst->alg.ivsize = LRW_BLOCK_SIZE; inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) + diff --git a/crypto/lz4.c b/crypto/lz4.c index 1e35134d..ed9088c9 100644 --- a/crypto/lz4.c +++ b/crypto/lz4.c @@ -119,6 +119,7 @@ static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, static struct crypto_alg alg_lz4 = { .cra_name = "lz4", + .cra_driver_name = "lz4-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct lz4_ctx), .cra_module = THIS_MODULE, diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c index 4a220b62..21a342c6 100644 --- a/crypto/lz4hc.c +++ b/crypto/lz4hc.c @@ -120,6 +120,7 @@ static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, static struct crypto_alg alg_lz4hc = { .cra_name = "lz4hc", + .cra_driver_name = "lz4hc-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct lz4hc_ctx), .cra_module = THIS_MODULE, diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c index 4c82bf18..46981492 100644 --- a/crypto/lzo-rle.c +++ b/crypto/lzo-rle.c @@ -122,6 +122,7 @@ static int lzorle_sdecompress(struct crypto_scomp *tfm, const u8 *src, static struct crypto_alg alg = { .cra_name = "lzo-rle", + .cra_driver_name = "lzo-rle-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct lzorle_ctx), .cra_module = THIS_MODULE, diff --git a/crypto/lzo.c b/crypto/lzo.c index 4a6ac8f2..a98ac046 100644 --- a/crypto/lzo.c +++ b/crypto/lzo.c @@ -122,6 +122,7 @@ static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src, static struct crypto_alg alg = { .cra_name = "lzo", + .cra_driver_name = "lzo-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct lzo_ctx), .cra_module = THIS_MODULE, diff --git a/crypto/md4.c b/crypto/md4.c index 9a1a228a..2e7f2f31 100644 --- a/crypto/md4.c +++ b/crypto/md4.c @@ -216,9 +216,10 @@ static struct shash_alg alg = { .final = md4_final, .descsize = sizeof(struct md4_ctx), .base = { - .cra_name = "md4", - .cra_blocksize = MD4_HMAC_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "md4", + .cra_driver_name = "md4-generic", + .cra_blocksize = MD4_HMAC_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }; diff --git a/crypto/md5.c b/crypto/md5.c index 221c2c09..22dc60bc 100644 --- a/crypto/md5.c +++ b/crypto/md5.c @@ -228,9 +228,10 @@ static struct shash_alg alg = { .descsize = sizeof(struct md5_state), .statesize = sizeof(struct md5_state), .base = { - .cra_name = "md5", - .cra_blocksize = MD5_HMAC_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "md5", + .cra_driver_name = "md5-generic", + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }; diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index 538ae793..be5c07ea 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -159,6 +159,7 @@ static struct shash_alg alg = { .descsize = sizeof(struct michael_mic_desc_ctx), .base = { .cra_name = "michael_mic", + .cra_driver_name = "michael_mic-generic", .cra_blocksize = 8, .cra_alignmask = 3, .cra_ctxsize = sizeof(struct michael_mic_ctx), diff --git a/crypto/rmd128.c b/crypto/rmd128.c index faf4252c..81fcae09 100644 --- a/crypto/rmd128.c +++ b/crypto/rmd128.c @@ -303,6 +303,7 @@ static struct shash_alg alg = { .descsize = sizeof(struct rmd128_ctx), .base = { .cra_name = "rmd128", + .cra_driver_name = "rmd128-generic", .cra_blocksize = RMD128_BLOCK_SIZE, .cra_module = THIS_MODULE, } diff --git a/crypto/rmd160.c b/crypto/rmd160.c index b3330991..0c0d178d 100644 --- a/crypto/rmd160.c +++ b/crypto/rmd160.c @@ -347,6 +347,7 @@ static struct shash_alg alg = { .descsize = sizeof(struct rmd160_ctx), .base = { .cra_name = "rmd160", + .cra_driver_name = "rmd160-generic", .cra_blocksize = RMD160_BLOCK_SIZE, .cra_module = THIS_MODULE, } diff --git a/crypto/rmd256.c b/crypto/rmd256.c index 2a643250..cdbbe372 100644 --- a/crypto/rmd256.c +++ b/crypto/rmd256.c @@ -322,6 +322,7 @@ static struct shash_alg alg = { .descsize = sizeof(struct rmd256_ctx), .base = { .cra_name = "rmd256", + .cra_driver_name = "rmd256-generic", .cra_blocksize = RMD256_BLOCK_SIZE, .cra_module = THIS_MODULE, } diff --git a/crypto/rmd320.c b/crypto/rmd320.c index 2f062574..9327af0f 100644 --- a/crypto/rmd320.c +++ b/crypto/rmd320.c @@ -371,6 +371,7 @@ static struct shash_alg alg = { .descsize = sizeof(struct rmd320_ctx), .base = { .cra_name = "rmd320", + .cra_driver_name = "rmd320-generic", .cra_blocksize = RMD320_BLOCK_SIZE, .cra_module = THIS_MODULE, } diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c index ec4ec89a..f2f54933 100644 --- a/crypto/serpent_generic.c +++ b/crypto/serpent_generic.c @@ -641,6 +641,7 @@ static struct crypto_alg srp_algs[2] = { { .cia_decrypt = serpent_decrypt } } }, { .cra_name = "tnepres", + .cra_driver_name = "tnepres-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = SERPENT_BLOCK_SIZE, .cra_ctxsize = sizeof(struct serpent_ctx), diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 2e66f312..2828e27d 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -842,6 +842,40 @@ static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, return 0; } +int crypto_skcipher_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_alg *alg = tfm->base.__crt_alg; + unsigned int cryptlen = req->cryptlen; + int ret; + + crypto_stats_get(alg); + if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + ret = -ENOKEY; + else + ret = tfm->encrypt(req); + crypto_stats_skcipher_encrypt(cryptlen, ret, alg); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_skcipher_encrypt); + +int crypto_skcipher_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_alg *alg = tfm->base.__crt_alg; + unsigned int cryptlen = req->cryptlen; + int ret; + + crypto_stats_get(alg); + if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + ret = -ENOKEY; + else + ret = tfm->decrypt(req); + crypto_stats_skcipher_decrypt(cryptlen, ret, alg); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_skcipher_decrypt); + static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm) { struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); diff --git a/crypto/tea.c b/crypto/tea.c index 786b589e..fa012589 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -221,6 +221,7 @@ static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) static struct crypto_alg tea_algs[3] = { { .cra_name = "tea", + .cra_driver_name = "tea-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct tea_ctx), @@ -234,6 +235,7 @@ static struct crypto_alg tea_algs[3] = { { .cia_decrypt = tea_decrypt } } }, { .cra_name = "xtea", + .cra_driver_name = "xtea-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), @@ -247,6 +249,7 @@ static struct crypto_alg tea_algs[3] = { { .cia_decrypt = xtea_decrypt } } }, { .cra_name = "xeta", + .cra_driver_name = "xeta-generic", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), diff --git a/crypto/testmgr.c b/crypto/testmgr.c index c9e67c2b..f7fdd7fe 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1037,6 +1037,205 @@ static void crypto_reenable_simd_for_test(void) } #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ +static int build_hash_sglist(struct test_sglist *tsgl, + const struct hash_testvec *vec, + const struct testvec_config *cfg, + unsigned int alignmask, + const struct test_sg_division *divs[XBUFSIZE]) +{ + struct kvec kv; + struct iov_iter input; + + kv.iov_base = (void *)vec->plaintext; + kv.iov_len = vec->psize; + iov_iter_kvec(&input, WRITE, &kv, 1, vec->psize); + return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize, + &input, divs); +} + +static int check_hash_result(const char *type, + const u8 *result, unsigned int digestsize, + const struct hash_testvec *vec, + const char *vec_name, + const char *driver, + const struct testvec_config *cfg) +{ + if (memcmp(result, vec->digest, digestsize) != 0) { + pr_err("alg: %s: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n", + type, driver, vec_name, cfg->name); + return -EINVAL; + } + if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) { + pr_err("alg: %s: %s overran result buffer on test vector %s, cfg=\"%s\"\n", + type, driver, vec_name, cfg->name); + return -EOVERFLOW; + } + return 0; +} + +static inline int check_shash_op(const char *op, int err, + const char *driver, const char *vec_name, + const struct testvec_config *cfg) +{ + if (err) + pr_err("alg: shash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n", + driver, op, err, vec_name, cfg->name); + return err; +} + +static inline const void *sg_data(struct scatterlist *sg) +{ + return page_address(sg_page(sg)) + sg->offset; +} + +/* Test one hash test vector in one configuration, using the shash API */ +static int test_shash_vec_cfg(const char *driver, + const struct hash_testvec *vec, + const char *vec_name, + const struct testvec_config *cfg, + struct shash_desc *desc, + struct test_sglist *tsgl, + u8 *hashstate) +{ + struct crypto_shash *tfm = desc->tfm; + const unsigned int alignmask = crypto_shash_alignmask(tfm); + const unsigned int digestsize = crypto_shash_digestsize(tfm); + const unsigned int statesize = crypto_shash_statesize(tfm); + const struct test_sg_division *divs[XBUFSIZE]; + unsigned int i; + u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN]; + int err; + + /* Set the key, if specified */ + if (vec->ksize) { + err = crypto_shash_setkey(tfm, vec->key, vec->ksize); + if (err) { + if (err == vec->setkey_error) + return 0; + pr_err("alg: shash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", + driver, vec_name, vec->setkey_error, err, + crypto_shash_get_flags(tfm)); + return err; + } + if (vec->setkey_error) { + pr_err("alg: shash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", + driver, vec_name, vec->setkey_error); + return -EINVAL; + } + } + + /* Build the scatterlist for the source data */ + err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs); + if (err) { + pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n", + driver, vec_name, cfg->name); + return err; + } + + /* Do the actual hashing */ + + testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm)); + testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); + + if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST || + vec->digest_error) { + /* Just using digest() */ + if (tsgl->nents != 1) + return 0; + if (cfg->nosimd) + crypto_disable_simd_for_test(); + err = crypto_shash_digest(desc, sg_data(&tsgl->sgl[0]), + tsgl->sgl[0].length, result); + if (cfg->nosimd) + crypto_reenable_simd_for_test(); + if (err) { + if (err == vec->digest_error) + return 0; + pr_err("alg: shash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", + driver, vec_name, vec->digest_error, err, + cfg->name); + return err; + } + if (vec->digest_error) { + pr_err("alg: shash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", + driver, vec_name, vec->digest_error, cfg->name); + return -EINVAL; + } + goto result_ready; + } + + /* Using init(), zero or more update(), then final() or finup() */ + + if (cfg->nosimd) + crypto_disable_simd_for_test(); + err = crypto_shash_init(desc); + if (cfg->nosimd) + crypto_reenable_simd_for_test(); + err = check_shash_op("init", err, driver, vec_name, cfg); + if (err) + return err; + + for (i = 0; i < tsgl->nents; i++) { + if (i + 1 == tsgl->nents && + cfg->finalization_type == FINALIZATION_TYPE_FINUP) { + if (divs[i]->nosimd) + crypto_disable_simd_for_test(); + err = crypto_shash_finup(desc, sg_data(&tsgl->sgl[i]), + tsgl->sgl[i].length, result); + if (divs[i]->nosimd) + crypto_reenable_simd_for_test(); + err = check_shash_op("finup", err, driver, vec_name, + cfg); + if (err) + return err; + goto result_ready; + } + if (divs[i]->nosimd) + crypto_disable_simd_for_test(); + err = crypto_shash_update(desc, sg_data(&tsgl->sgl[i]), + tsgl->sgl[i].length); + if (divs[i]->nosimd) + crypto_reenable_simd_for_test(); + err = check_shash_op("update", err, driver, vec_name, cfg); + if (err) + return err; + if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) { + /* Test ->export() and ->import() */ + testmgr_poison(hashstate + statesize, + TESTMGR_POISON_LEN); + err = crypto_shash_export(desc, hashstate); + err = check_shash_op("export", err, driver, vec_name, + cfg); + if (err) + return err; + if (!testmgr_is_poison(hashstate + statesize, + TESTMGR_POISON_LEN)) { + pr_err("alg: shash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n", + driver, vec_name, cfg->name); + return -EOVERFLOW; + } + testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm)); + err = crypto_shash_import(desc, hashstate); + err = check_shash_op("import", err, driver, vec_name, + cfg); + if (err) + return err; + } + } + + if (cfg->nosimd) + crypto_disable_simd_for_test(); + err = crypto_shash_final(desc, result); + if (cfg->nosimd) + crypto_reenable_simd_for_test(); + err = check_shash_op("final", err, driver, vec_name, cfg); + if (err) + return err; +result_ready: + return check_hash_result("shash", result, digestsize, vec, vec_name, + driver, cfg); +} + static int do_ahash_op(int (*op)(struct ahash_request *req), struct ahash_request *req, struct crypto_wait *wait, bool nosimd) @@ -1054,31 +1253,32 @@ static int do_ahash_op(int (*op)(struct ahash_request *req), return crypto_wait_req(err, wait); } -static int check_nonfinal_hash_op(const char *op, int err, - u8 *result, unsigned int digestsize, - const char *driver, const char *vec_name, - const struct testvec_config *cfg) +static int check_nonfinal_ahash_op(const char *op, int err, + u8 *result, unsigned int digestsize, + const char *driver, const char *vec_name, + const struct testvec_config *cfg) { if (err) { - pr_err("alg: hash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n", driver, op, err, vec_name, cfg->name); return err; } if (!testmgr_is_poison(result, digestsize)) { - pr_err("alg: hash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n", driver, op, vec_name, cfg->name); return -EINVAL; } return 0; } -static int test_hash_vec_cfg(const char *driver, - const struct hash_testvec *vec, - const char *vec_name, - const struct testvec_config *cfg, - struct ahash_request *req, - struct test_sglist *tsgl, - u8 *hashstate) +/* Test one hash test vector in one configuration, using the ahash API */ +static int test_ahash_vec_cfg(const char *driver, + const struct hash_testvec *vec, + const char *vec_name, + const struct testvec_config *cfg, + struct ahash_request *req, + struct test_sglist *tsgl, + u8 *hashstate) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); const unsigned int alignmask = crypto_ahash_alignmask(tfm); @@ -1087,8 +1287,6 @@ static int test_hash_vec_cfg(const char *driver, const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags; const struct test_sg_division *divs[XBUFSIZE]; DECLARE_CRYPTO_WAIT(wait); - struct kvec _input; - struct iov_iter input; unsigned int i; struct scatterlist *pending_sgl; unsigned int pending_len; @@ -1101,26 +1299,22 @@ static int test_hash_vec_cfg(const char *driver, if (err) { if (err == vec->setkey_error) return 0; - pr_err("alg: hash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", + pr_err("alg: ahash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", driver, vec_name, vec->setkey_error, err, crypto_ahash_get_flags(tfm)); return err; } if (vec->setkey_error) { - pr_err("alg: hash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", + pr_err("alg: ahash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", driver, vec_name, vec->setkey_error); return -EINVAL; } } /* Build the scatterlist for the source data */ - _input.iov_base = (void *)vec->plaintext; - _input.iov_len = vec->psize; - iov_iter_kvec(&input, WRITE, &_input, 1, vec->psize); - err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize, - &input, divs); + err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs); if (err) { - pr_err("alg: hash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n", driver, vec_name, cfg->name); return err; } @@ -1140,13 +1334,13 @@ static int test_hash_vec_cfg(const char *driver, if (err) { if (err == vec->digest_error) return 0; - pr_err("alg: hash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", + pr_err("alg: ahash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", driver, vec_name, vec->digest_error, err, cfg->name); return err; } if (vec->digest_error) { - pr_err("alg: hash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", + pr_err("alg: ahash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", driver, vec_name, vec->digest_error, cfg->name); return -EINVAL; } @@ -1158,8 +1352,8 @@ static int test_hash_vec_cfg(const char *driver, ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); ahash_request_set_crypt(req, NULL, result, 0); err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd); - err = check_nonfinal_hash_op("init", err, result, digestsize, - driver, vec_name, cfg); + err = check_nonfinal_ahash_op("init", err, result, digestsize, + driver, vec_name, cfg); if (err) return err; @@ -1175,9 +1369,9 @@ static int test_hash_vec_cfg(const char *driver, pending_len); err = do_ahash_op(crypto_ahash_update, req, &wait, divs[i]->nosimd); - err = check_nonfinal_hash_op("update", err, - result, digestsize, - driver, vec_name, cfg); + err = check_nonfinal_ahash_op("update", err, + result, digestsize, + driver, vec_name, cfg); if (err) return err; pending_sgl = NULL; @@ -1188,23 +1382,23 @@ static int test_hash_vec_cfg(const char *driver, testmgr_poison(hashstate + statesize, TESTMGR_POISON_LEN); err = crypto_ahash_export(req, hashstate); - err = check_nonfinal_hash_op("export", err, - result, digestsize, - driver, vec_name, cfg); + err = check_nonfinal_ahash_op("export", err, + result, digestsize, + driver, vec_name, cfg); if (err) return err; if (!testmgr_is_poison(hashstate + statesize, TESTMGR_POISON_LEN)) { - pr_err("alg: hash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n", driver, vec_name, cfg->name); return -EOVERFLOW; } testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); err = crypto_ahash_import(req, hashstate); - err = check_nonfinal_hash_op("import", err, - result, digestsize, - driver, vec_name, cfg); + err = check_nonfinal_ahash_op("import", err, + result, digestsize, + driver, vec_name, cfg); if (err) return err; } @@ -1218,13 +1412,13 @@ static int test_hash_vec_cfg(const char *driver, if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) { /* finish with update() and final() */ err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd); - err = check_nonfinal_hash_op("update", err, result, digestsize, - driver, vec_name, cfg); + err = check_nonfinal_ahash_op("update", err, result, digestsize, + driver, vec_name, cfg); if (err) return err; err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd); if (err) { - pr_err("alg: hash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n", driver, err, vec_name, cfg->name); return err; } @@ -1232,31 +1426,49 @@ static int test_hash_vec_cfg(const char *driver, /* finish with finup() */ err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd); if (err) { - pr_err("alg: hash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n", + pr_err("alg: ahash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n", driver, err, vec_name, cfg->name); return err; } } result_ready: - /* Check that the algorithm produced the correct digest */ - if (memcmp(result, vec->digest, digestsize) != 0) { - pr_err("alg: hash: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n", - driver, vec_name, cfg->name); - return -EINVAL; - } - if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) { - pr_err("alg: hash: %s overran result buffer on test vector %s, cfg=\"%s\"\n", - driver, vec_name, cfg->name); - return -EOVERFLOW; + return check_hash_result("ahash", result, digestsize, vec, vec_name, + driver, cfg); +} + +static int test_hash_vec_cfg(const char *driver, + const struct hash_testvec *vec, + const char *vec_name, + const struct testvec_config *cfg, + struct ahash_request *req, + struct shash_desc *desc, + struct test_sglist *tsgl, + u8 *hashstate) +{ + int err; + + /* + * For algorithms implemented as "shash", most bugs will be detected by + * both the shash and ahash tests. Test the shash API first so that the + * failures involve less indirection, so are easier to debug. + */ + + if (desc) { + err = test_shash_vec_cfg(driver, vec, vec_name, cfg, desc, tsgl, + hashstate); + if (err) + return err; } - return 0; + return test_ahash_vec_cfg(driver, vec, vec_name, cfg, req, tsgl, + hashstate); } static int test_hash_vec(const char *driver, const struct hash_testvec *vec, unsigned int vec_num, struct ahash_request *req, - struct test_sglist *tsgl, u8 *hashstate) + struct shash_desc *desc, struct test_sglist *tsgl, + u8 *hashstate) { char vec_name[16]; unsigned int i; @@ -1267,7 +1479,7 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec, for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) { err = test_hash_vec_cfg(driver, vec, vec_name, &default_hash_testvec_configs[i], - req, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) return err; } @@ -1281,9 +1493,10 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec, generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname)); err = test_hash_vec_cfg(driver, vec, vec_name, &cfg, - req, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) return err; + cond_resched(); } } #endif @@ -1343,6 +1556,7 @@ static int test_hash_vs_generic_impl(const char *driver, const char *generic_driver, unsigned int maxkeysize, struct ahash_request *req, + struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) { @@ -1423,7 +1637,7 @@ static int test_hash_vs_generic_impl(const char *driver, generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname)); err = test_hash_vec_cfg(driver, &vec, vec_name, &cfg, - req, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) goto out; cond_resched(); @@ -1441,6 +1655,7 @@ static int test_hash_vs_generic_impl(const char *driver, const char *generic_driver, unsigned int maxkeysize, struct ahash_request *req, + struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) { @@ -1448,26 +1663,67 @@ static int test_hash_vs_generic_impl(const char *driver, } #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ +static int alloc_shash(const char *driver, u32 type, u32 mask, + struct crypto_shash **tfm_ret, + struct shash_desc **desc_ret) +{ + struct crypto_shash *tfm; + struct shash_desc *desc; + + tfm = crypto_alloc_shash(driver, type, mask); + if (IS_ERR(tfm)) { + if (PTR_ERR(tfm) == -ENOENT) { + /* + * This algorithm is only available through the ahash + * API, not the shash API, so skip the shash tests. + */ + return 0; + } + pr_err("alg: hash: failed to allocate shash transform for %s: %ld\n", + driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); + if (!desc) { + crypto_free_shash(tfm); + return -ENOMEM; + } + desc->tfm = tfm; + + *tfm_ret = tfm; + *desc_ret = desc; + return 0; +} + static int __alg_test_hash(const struct hash_testvec *vecs, unsigned int num_vecs, const char *driver, u32 type, u32 mask, const char *generic_driver, unsigned int maxkeysize) { - struct crypto_ahash *tfm; + struct crypto_ahash *atfm = NULL; struct ahash_request *req = NULL; + struct crypto_shash *stfm = NULL; + struct shash_desc *desc = NULL; struct test_sglist *tsgl = NULL; u8 *hashstate = NULL; + unsigned int statesize; unsigned int i; int err; - tfm = crypto_alloc_ahash(driver, type, mask); - if (IS_ERR(tfm)) { + /* + * Always test the ahash API. This works regardless of whether the + * algorithm is implemented as ahash or shash. + */ + + atfm = crypto_alloc_ahash(driver, type, mask); + if (IS_ERR(atfm)) { pr_err("alg: hash: failed to allocate transform for %s: %ld\n", - driver, PTR_ERR(tfm)); - return PTR_ERR(tfm); + driver, PTR_ERR(atfm)); + return PTR_ERR(atfm); } - req = ahash_request_alloc(tfm, GFP_KERNEL); + req = ahash_request_alloc(atfm, GFP_KERNEL); if (!req) { pr_err("alg: hash: failed to allocate request for %s\n", driver); @@ -1475,6 +1731,14 @@ static int __alg_test_hash(const struct hash_testvec *vecs, goto out; } + /* + * If available also test the shash API, to cover corner cases that may + * be missed by testing the ahash API only. + */ + err = alloc_shash(driver, type, mask, &stfm, &desc); + if (err) + goto out; + tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL); if (!tsgl || init_test_sglist(tsgl) != 0) { pr_err("alg: hash: failed to allocate test buffers for %s\n", @@ -1485,8 +1749,10 @@ static int __alg_test_hash(const struct hash_testvec *vecs, goto out; } - hashstate = kmalloc(crypto_ahash_statesize(tfm) + TESTMGR_POISON_LEN, - GFP_KERNEL); + statesize = crypto_ahash_statesize(atfm); + if (stfm) + statesize = max(statesize, crypto_shash_statesize(stfm)); + hashstate = kmalloc(statesize + TESTMGR_POISON_LEN, GFP_KERNEL); if (!hashstate) { pr_err("alg: hash: failed to allocate hash state buffer for %s\n", driver); @@ -1495,20 +1761,24 @@ static int __alg_test_hash(const struct hash_testvec *vecs, } for (i = 0; i < num_vecs; i++) { - err = test_hash_vec(driver, &vecs[i], i, req, tsgl, hashstate); + err = test_hash_vec(driver, &vecs[i], i, req, desc, tsgl, + hashstate); if (err) goto out; + cond_resched(); } err = test_hash_vs_generic_impl(driver, generic_driver, maxkeysize, req, - tsgl, hashstate); + desc, tsgl, hashstate); out: kfree(hashstate); if (tsgl) { destroy_test_sglist(tsgl); kfree(tsgl); } + kfree(desc); + crypto_free_shash(stfm); ahash_request_free(req); - crypto_free_ahash(tfm); + crypto_free_ahash(atfm); return err; } @@ -1760,6 +2030,7 @@ static int test_aead_vec(const char *driver, int enc, &cfg, req, tsgls); if (err) return err; + cond_resched(); } } #endif @@ -1999,6 +2270,7 @@ static int test_aead(const char *driver, int enc, tsgls); if (err) return err; + cond_resched(); } return 0; } @@ -2341,6 +2613,7 @@ static int test_skcipher_vec(const char *driver, int enc, &cfg, req, tsgls); if (err) return err; + cond_resched(); } } #endif @@ -2540,6 +2813,7 @@ static int test_skcipher(const char *driver, int enc, tsgls); if (err) return err; + cond_resched(); } return 0; } @@ -4795,6 +5069,13 @@ static const struct alg_test_desc alg_test_descs[] = { .test = alg_test_null, .fips_allowed = 1, }, { + .alg = "xxhash64", + .test = alg_test_hash, + .fips_allowed = 1, + .suite = { + .hash = __VECS(xxhash64_tv_template) + } + }, { .alg = "zlib-deflate", .test = alg_test_comp, .fips_allowed = 1, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 9a13c634..6b459a6a 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -43,7 +43,7 @@ struct hash_testvec { const char *key; const char *plaintext; const char *digest; - unsigned short psize; + unsigned int psize; unsigned short ksize; int setkey_error; int digest_error; @@ -74,7 +74,7 @@ struct cipher_testvec { const char *ctext; unsigned char wk; /* weak key flag */ unsigned short klen; - unsigned short len; + unsigned int len; bool fips_skip; bool generates_iv; int setkey_error; @@ -110,9 +110,9 @@ struct aead_testvec { unsigned char novrfy; unsigned char wk; unsigned char klen; - unsigned short plen; - unsigned short clen; - unsigned short alen; + unsigned int plen; + unsigned int clen; + unsigned int alen; int setkey_error; int setauthsize_error; int crypt_error; @@ -5803,7 +5803,49 @@ static const struct hash_testvec poly1305_tv_template[] = { .psize = 80, .digest = "\x13\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00", - }, + }, { /* Regression test for overflow in AVX2 implementation */ + .plaintext = "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff", + .psize = 300, + .digest = "\xfb\x5e\x96\xd8\x61\xd5\xc7\xc8" + "\x78\xe5\x87\xcc\x2d\x5a\x22\xe1", + } }; /* NHPoly1305 test vectors from https://github.com/google/adiantum */ @@ -33345,6 +33387,112 @@ static const struct hash_testvec crc32c_tv_template[] = { } }; +static const struct hash_testvec xxhash64_tv_template[] = { + { + .psize = 0, + .digest = "\x99\xe9\xd8\x51\x37\xdb\x46\xef", + }, + { + .plaintext = "\x40", + .psize = 1, + .digest = "\x20\x5c\x91\xaa\x88\xeb\x59\xd0", + }, + { + .plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d" + "\x88\xc7\x9a\x09\x1a\x9b", + .psize = 14, + .digest = "\xa8\xe8\x2b\xa9\x92\xa1\x37\x4a", + }, + { + .plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d" + "\x88\xc7\x9a\x09\x1a\x9b\x42\xe0" + "\xd4\x38\xa5\x2a\x26\xa5\x19\x4b" + "\x57\x65\x7f\xad\xc3\x7d\xca\x40" + "\x31\x65\x05\xbb\x31\xae\x51\x11" + "\xa8\xc0\xb3\x28\x42\xeb\x3c\x46" + "\xc8\xed\xed\x0f\x8d\x0b\xfa\x6e" + "\xbc\xe3\x88\x53\xca\x8f\xc8\xd9" + "\x41\x26\x7a\x3d\x21\xdb\x1a\x3c" + "\x01\x1d\xc9\xe9\xb7\x3a\x78\x67" + "\x57\x20\x94\xf1\x1e\xfd\xce\x39" + "\x99\x57\x69\x39\xa5\xd0\x8d\xd9" + "\x43\xfe\x1d\x66\x04\x3c\x27\x6a" + "\xe1\x0d\xe7\xc9\xfa\xc9\x07\x56" + "\xa5\xb3\xec\xd9\x1f\x42\x65\x66" + "\xaa\xbf\x87\x9b\xc5\x41\x9c\x27" + "\x3f\x2f\xa9\x55\x93\x01\x27\x33" + "\x43\x99\x4d\x81\x85\xae\x82\x00" + "\x6c\xd0\xd1\xa3\x57\x18\x06\xcc" + "\xec\x72\xf7\x8e\x87\x2d\x1f\x5e" + "\xd7\x5b\x1f\x36\x4c\xfa\xfd\x18" + "\x89\x76\xd3\x5e\xb5\x5a\xc0\x01" + "\xd2\xa1\x9a\x50\xe6\x08\xb4\x76" + "\x56\x4f\x0e\xbc\x54\xfc\x67\xe6" + "\xb9\xc0\x28\x4b\xb5\xc3\xff\x79" + "\x52\xea\xa1\x90\xc3\xaf\x08\x70" + "\x12\x02\x0c\xdb\x94\x00\x38\x95" + "\xed\xfd\x08\xf7\xe8\x04", + .psize = 222, + .digest = "\x41\xfc\xd4\x29\xfe\xe7\x85\x17", + }, + { + .psize = 0, + .key = "\xb1\x79\x37\x9e\x00\x00\x00\x00", + .ksize = 8, + .digest = "\xef\x17\x9b\x92\xa2\xfd\x75\xac", + }, + + { + .plaintext = "\x40", + .psize = 1, + .key = "\xb1\x79\x37\x9e\x00\x00\x00\x00", + .ksize = 8, + .digest = "\xd1\x70\x4f\x14\x02\xc4\x9e\x71", + }, + { + .plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d" + "\x88\xc7\x9a\x09\x1a\x9b", + .psize = 14, + .key = "\xb1\x79\x37\x9e\x00\x00\x00\x00", + .ksize = 8, + .digest = "\xa4\xcd\xfe\x8e\x37\xe2\x1c\x64" + }, + { + .plaintext = "\x40\x8b\xb8\x41\xe4\x42\x15\x2d" + "\x88\xc7\x9a\x09\x1a\x9b\x42\xe0" + "\xd4\x38\xa5\x2a\x26\xa5\x19\x4b" + "\x57\x65\x7f\xad\xc3\x7d\xca\x40" + "\x31\x65\x05\xbb\x31\xae\x51\x11" + "\xa8\xc0\xb3\x28\x42\xeb\x3c\x46" + "\xc8\xed\xed\x0f\x8d\x0b\xfa\x6e" + "\xbc\xe3\x88\x53\xca\x8f\xc8\xd9" + "\x41\x26\x7a\x3d\x21\xdb\x1a\x3c" + "\x01\x1d\xc9\xe9\xb7\x3a\x78\x67" + "\x57\x20\x94\xf1\x1e\xfd\xce\x39" + "\x99\x57\x69\x39\xa5\xd0\x8d\xd9" + "\x43\xfe\x1d\x66\x04\x3c\x27\x6a" + "\xe1\x0d\xe7\xc9\xfa\xc9\x07\x56" + "\xa5\xb3\xec\xd9\x1f\x42\x65\x66" + "\xaa\xbf\x87\x9b\xc5\x41\x9c\x27" + "\x3f\x2f\xa9\x55\x93\x01\x27\x33" + "\x43\x99\x4d\x81\x85\xae\x82\x00" + "\x6c\xd0\xd1\xa3\x57\x18\x06\xcc" + "\xec\x72\xf7\x8e\x87\x2d\x1f\x5e" + "\xd7\x5b\x1f\x36\x4c\xfa\xfd\x18" + "\x89\x76\xd3\x5e\xb5\x5a\xc0\x01" + "\xd2\xa1\x9a\x50\xe6\x08\xb4\x76" + "\x56\x4f\x0e\xbc\x54\xfc\x67\xe6" + "\xb9\xc0\x28\x4b\xb5\xc3\xff\x79" + "\x52\xea\xa1\x90\xc3\xaf\x08\x70" + "\x12\x02\x0c\xdb\x94\x00\x38\x95" + "\xed\xfd\x08\xf7\xe8\x04", + .psize = 222, + .key = "\xb1\x79\x37\x9e\x00\x00\x00\x00", + .ksize = 8, + .digest = "\x58\xbc\x55\xf2\x42\x81\x5c\xf0" + }, +}; + static const struct comp_testvec lz4_comp_tv_template[] = { { .inlen = 255, diff --git a/crypto/tgr192.c b/crypto/tgr192.c index 40020f8a..39b3ffd2 100644 --- a/crypto/tgr192.c +++ b/crypto/tgr192.c @@ -635,9 +635,10 @@ static struct shash_alg tgr_algs[3] = { { .final = tgr192_final, .descsize = sizeof(struct tgr192_ctx), .base = { - .cra_name = "tgr192", - .cra_blocksize = TGR192_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "tgr192", + .cra_driver_name = "tgr192-generic", + .cra_blocksize = TGR192_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }, { .digestsize = TGR160_DIGEST_SIZE, @@ -646,9 +647,10 @@ static struct shash_alg tgr_algs[3] = { { .final = tgr160_final, .descsize = sizeof(struct tgr192_ctx), .base = { - .cra_name = "tgr160", - .cra_blocksize = TGR192_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "tgr160", + .cra_driver_name = "tgr160-generic", + .cra_blocksize = TGR192_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }, { .digestsize = TGR128_DIGEST_SIZE, @@ -657,9 +659,10 @@ static struct shash_alg tgr_algs[3] = { { .final = tgr128_final, .descsize = sizeof(struct tgr192_ctx), .base = { - .cra_name = "tgr128", - .cra_blocksize = TGR192_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "tgr128", + .cra_driver_name = "tgr128-generic", + .cra_blocksize = TGR192_BLOCK_SIZE, + .cra_module = THIS_MODULE, } } }; diff --git a/crypto/wp512.c b/crypto/wp512.c index 1b8e502d..feadc13c 100644 --- a/crypto/wp512.c +++ b/crypto/wp512.c @@ -1126,9 +1126,10 @@ static struct shash_alg wp_algs[3] = { { .final = wp512_final, .descsize = sizeof(struct wp512_ctx), .base = { - .cra_name = "wp512", - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "wp512", + .cra_driver_name = "wp512-generic", + .cra_blocksize = WP512_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }, { .digestsize = WP384_DIGEST_SIZE, @@ -1137,9 +1138,10 @@ static struct shash_alg wp_algs[3] = { { .final = wp384_final, .descsize = sizeof(struct wp512_ctx), .base = { - .cra_name = "wp384", - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "wp384", + .cra_driver_name = "wp384-generic", + .cra_blocksize = WP512_BLOCK_SIZE, + .cra_module = THIS_MODULE, } }, { .digestsize = WP256_DIGEST_SIZE, @@ -1148,9 +1150,10 @@ static struct shash_alg wp_algs[3] = { { .final = wp256_final, .descsize = sizeof(struct wp512_ctx), .base = { - .cra_name = "wp256", - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, + .cra_name = "wp256", + .cra_driver_name = "wp256-generic", + .cra_blocksize = WP512_BLOCK_SIZE, + .cra_module = THIS_MODULE, } } }; diff --git a/crypto/xts.c b/crypto/xts.c index aed11e63..33cf726d 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -137,8 +137,12 @@ static void crypt_done(struct crypto_async_request *areq, int err) { struct skcipher_request *req = areq->data; - if (!err) + if (!err) { + struct rctx *rctx = skcipher_request_ctx(req); + + rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; err = xor_tweak_post(req); + } skcipher_request_complete(req, err); } diff --git a/crypto/xxhash_generic.c b/crypto/xxhash_generic.c new file mode 100644 index 00000000..4aad2c0f --- /dev/null +++ b/crypto/xxhash_generic.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <crypto/internal/hash.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/xxhash.h> +#include <asm/unaligned.h> + +#define XXHASH64_BLOCK_SIZE 32 +#define XXHASH64_DIGEST_SIZE 8 + +struct xxhash64_tfm_ctx { + u64 seed; +}; + +struct xxhash64_desc_ctx { + struct xxh64_state xxhstate; +}; + +static int xxhash64_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen) +{ + struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(tfm); + + if (keylen != sizeof(tctx->seed)) { + crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + tctx->seed = get_unaligned_le64(key); + return 0; +} + +static int xxhash64_init(struct shash_desc *desc) +{ + struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc); + + xxh64_reset(&dctx->xxhstate, tctx->seed); + + return 0; +} + +static int xxhash64_update(struct shash_desc *desc, const u8 *data, + unsigned int length) +{ + struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc); + + xxh64_update(&dctx->xxhstate, data, length); + + return 0; +} + +static int xxhash64_final(struct shash_desc *desc, u8 *out) +{ + struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc); + + put_unaligned_le64(xxh64_digest(&dctx->xxhstate), out); + + return 0; +} + +static int xxhash64_digest(struct shash_desc *desc, const u8 *data, + unsigned int length, u8 *out) +{ + struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + + put_unaligned_le64(xxh64(data, length, tctx->seed), out); + + return 0; +} + +static struct shash_alg alg = { + .digestsize = XXHASH64_DIGEST_SIZE, + .setkey = xxhash64_setkey, + .init = xxhash64_init, + .update = xxhash64_update, + .final = xxhash64_final, + .digest = xxhash64_digest, + .descsize = sizeof(struct xxhash64_desc_ctx), + .base = { + .cra_name = "xxhash64", + .cra_driver_name = "xxhash64-generic", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = XXHASH64_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct xxhash64_tfm_ctx), + .cra_module = THIS_MODULE, + } +}; + +static int __init xxhash_mod_init(void) +{ + return crypto_register_shash(&alg); +} + +static void __exit xxhash_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +subsys_initcall(xxhash_mod_init); +module_exit(xxhash_mod_fini); + +MODULE_AUTHOR("Nikolay Borisov <nborisov@suse.com>"); +MODULE_DESCRIPTION("xxhash calculations wrapper for lib/xxhash.c"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CRYPTO("xxhash64"); +MODULE_ALIAS_CRYPTO("xxhash64-generic"); diff --git a/crypto/zstd.c b/crypto/zstd.c index 2c04055e..c9ff2ec8 100644 --- a/crypto/zstd.c +++ b/crypto/zstd.c @@ -214,6 +214,7 @@ static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src, static struct crypto_alg alg = { .cra_name = "zstd", + .cra_driver_name = "zstd-generic", .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, .cra_ctxsize = sizeof(struct zstd_ctx), .cra_module = THIS_MODULE, |