From 07bfd9bdf568a38d9440c607b72342036011f727 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 19 Nov 2019 17:41:31 +0800 Subject: crypto: pcrypt - Fix user-after-free on module unload On module unload of pcrypt we must unregister the crypto algorithms first and then tear down the padata structure. As otherwise the crypto algorithms are still alive and can be used while the padata structure is being freed. Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto...") Cc: Signed-off-by: Herbert Xu --- crypto/pcrypt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index 543792e0ebf0..81bbea7f2ba6 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -362,11 +362,12 @@ err: static void __exit pcrypt_exit(void) { + crypto_unregister_template(&pcrypt_tmpl); + pcrypt_fini_padata(pencrypt); pcrypt_fini_padata(pdecrypt); kset_unregister(pcrypt_kset); - crypto_unregister_template(&pcrypt_tmpl); } subsys_initcall(pcrypt_init); -- cgit v1.2.3 From bbefa1dd6a6d53537c11624752219e39959d04fb Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 26 Nov 2019 15:58:45 +0800 Subject: crypto: pcrypt - Avoid deadlock by using per-instance padata queues If the pcrypt template is used multiple times in an algorithm, then a deadlock occurs because all pcrypt instances share the same padata_instance, which completes requests in the order submitted. That is, the inner pcrypt request waits for the outer pcrypt request while the outer request is already waiting for the inner. This patch fixes this by allocating a set of queues for each pcrypt instance instead of using two global queues. In order to maintain the existing user-space interface, the pinst structure remains global so any sysfs modifications will apply to every pcrypt instance. Note that when an update occurs we have to allocate memory for every pcrypt instance. Should one of the allocations fail we will abort the update without rolling back changes already made. The new per-instance data structure is called padata_shell and is essentially a wrapper around parallel_data. Reproducer: #include #include #include int main() { struct sockaddr_alg addr = { .salg_type = "aead", .salg_name = "pcrypt(pcrypt(rfc4106-gcm-aesni))" }; int algfd, reqfd; char buf[32] = { 0 }; algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(algfd, (void *)&addr, sizeof(addr)); setsockopt(algfd, SOL_ALG, ALG_SET_KEY, buf, 20); reqfd = accept(algfd, 0, 0); write(reqfd, buf, 32); read(reqfd, buf, 16); } Reported-by: syzbot+56c7151cad94eec37c521f0e47d2eee53f9361c4@syzkaller.appspotmail.com Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper") Signed-off-by: Herbert Xu Tested-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/pcrypt.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index 81bbea7f2ba6..3e026e7a7e75 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -24,6 +24,8 @@ static struct kset *pcrypt_kset; struct pcrypt_instance_ctx { struct crypto_aead_spawn spawn; + struct padata_shell *psenc; + struct padata_shell *psdec; atomic_t tfm_count; }; @@ -32,6 +34,12 @@ struct pcrypt_aead_ctx { unsigned int cb_cpu; }; +static inline struct pcrypt_instance_ctx *pcrypt_tfm_ictx( + struct crypto_aead *tfm) +{ + return aead_instance_ctx(aead_alg_instance(tfm)); +} + static int pcrypt_aead_setkey(struct crypto_aead *parent, const u8 *key, unsigned int keylen) { @@ -90,6 +98,9 @@ static int pcrypt_aead_encrypt(struct aead_request *req) struct crypto_aead *aead = crypto_aead_reqtfm(req); struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead); u32 flags = aead_request_flags(req); + struct pcrypt_instance_ctx *ictx; + + ictx = pcrypt_tfm_ictx(aead); memset(padata, 0, sizeof(struct padata_priv)); @@ -103,7 +114,7 @@ static int pcrypt_aead_encrypt(struct aead_request *req) req->cryptlen, req->iv); aead_request_set_ad(creq, req->assoclen); - err = padata_do_parallel(pencrypt, padata, &ctx->cb_cpu); + err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu); if (!err) return -EINPROGRESS; @@ -132,6 +143,9 @@ static int pcrypt_aead_decrypt(struct aead_request *req) struct crypto_aead *aead = crypto_aead_reqtfm(req); struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead); u32 flags = aead_request_flags(req); + struct pcrypt_instance_ctx *ictx; + + ictx = pcrypt_tfm_ictx(aead); memset(padata, 0, sizeof(struct padata_priv)); @@ -145,7 +159,7 @@ static int pcrypt_aead_decrypt(struct aead_request *req) req->cryptlen, req->iv); aead_request_set_ad(creq, req->assoclen); - err = padata_do_parallel(pdecrypt, padata, &ctx->cb_cpu); + err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu); if (!err) return -EINPROGRESS; @@ -192,6 +206,8 @@ static void pcrypt_free(struct aead_instance *inst) struct pcrypt_instance_ctx *ctx = aead_instance_ctx(inst); crypto_drop_aead(&ctx->spawn); + padata_free_shell(ctx->psdec); + padata_free_shell(ctx->psenc); kfree(inst); } @@ -233,12 +249,22 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb, if (!inst) return -ENOMEM; + err = -ENOMEM; + ctx = aead_instance_ctx(inst); + ctx->psenc = padata_alloc_shell(pencrypt); + if (!ctx->psenc) + goto out_free_inst; + + ctx->psdec = padata_alloc_shell(pdecrypt); + if (!ctx->psdec) + goto out_free_psenc; + crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst)); err = crypto_grab_aead(&ctx->spawn, name, 0, 0); if (err) - goto out_free_inst; + goto out_free_psdec; alg = crypto_spawn_aead_alg(&ctx->spawn); err = pcrypt_init_instance(aead_crypto_instance(inst), &alg->base); @@ -271,6 +297,10 @@ out: out_drop_aead: crypto_drop_aead(&ctx->spawn); +out_free_psdec: + padata_free_shell(ctx->psdec); +out_free_psenc: + padata_free_shell(ctx->psenc); out_free_inst: kfree(inst); goto out; -- cgit v1.2.3 From 9c1e8836edbbaf3656bc07437b59c04be034ac4e Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 26 Nov 2019 22:08:02 -0800 Subject: crypto: x86 - Regularize glue function prototypes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The crypto glue performed function prototype casting via macros to make indirect calls to assembly routines. Instead of performing casts at the call sites (which trips Control Flow Integrity prototype checking), switch each prototype to a common standard set of arguments which allows the removal of the existing macros. In order to keep pointer math unchanged, internal casting between u128 pointers and u8 pointers is added. Co-developed-by: João Moreira Signed-off-by: João Moreira Signed-off-by: Kees Cook Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/cast6_generic.c | 18 ++++++++++-------- crypto/serpent_generic.c | 6 ++++-- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'crypto') diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c index a8248f8e2777..85328522c5ca 100644 --- a/crypto/cast6_generic.c +++ b/crypto/cast6_generic.c @@ -154,7 +154,7 @@ int cast6_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) EXPORT_SYMBOL_GPL(cast6_setkey); /*forward quad round*/ -static inline void Q(u32 *block, u8 *Kr, u32 *Km) +static inline void Q(u32 *block, const u8 *Kr, const u32 *Km) { u32 I; block[2] ^= F1(block[3], Kr[0], Km[0]); @@ -164,7 +164,7 @@ static inline void Q(u32 *block, u8 *Kr, u32 *Km) } /*reverse quad round*/ -static inline void QBAR(u32 *block, u8 *Kr, u32 *Km) +static inline void QBAR(u32 *block, const u8 *Kr, const u32 *Km) { u32 I; block[3] ^= F1(block[0], Kr[3], Km[3]); @@ -173,13 +173,14 @@ static inline void QBAR(u32 *block, u8 *Kr, u32 *Km) block[2] ^= F1(block[3], Kr[0], Km[0]); } -void __cast6_encrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf) +void __cast6_encrypt(const void *ctx, u8 *outbuf, const u8 *inbuf) { + const struct cast6_ctx *c = ctx; const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 block[4]; - u32 *Km; - u8 *Kr; + const u32 *Km; + const u8 *Kr; block[0] = be32_to_cpu(src[0]); block[1] = be32_to_cpu(src[1]); @@ -211,13 +212,14 @@ static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) __cast6_encrypt(crypto_tfm_ctx(tfm), outbuf, inbuf); } -void __cast6_decrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf) +void __cast6_decrypt(const void *ctx, u8 *outbuf, const u8 *inbuf) { + const struct cast6_ctx *c = ctx; const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 block[4]; - u32 *Km; - u8 *Kr; + const u32 *Km; + const u8 *Kr; block[0] = be32_to_cpu(src[0]); block[1] = be32_to_cpu(src[1]); diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c index 56fa665a4f01..492c1d0bfe06 100644 --- a/crypto/serpent_generic.c +++ b/crypto/serpent_generic.c @@ -449,8 +449,9 @@ int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) } EXPORT_SYMBOL_GPL(serpent_setkey); -void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src) +void __serpent_encrypt(const void *c, u8 *dst, const u8 *src) { + const struct serpent_ctx *ctx = c; const u32 *k = ctx->expkey; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; @@ -514,8 +515,9 @@ static void serpent_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) __serpent_encrypt(ctx, dst, src); } -void __serpent_decrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src) +void __serpent_decrypt(const void *c, u8 *dst, const u8 *src) { + const struct serpent_ctx *ctx = c; const u32 *k = ctx->expkey; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; -- cgit v1.2.3 From e8d998264bffade3cfe0536559f712ab9058d654 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 29 Nov 2019 16:40:24 +0800 Subject: crypto: pcrypt - Do not clear MAY_SLEEP flag in original request We should not be modifying the original request's MAY_SLEEP flag upon completion. It makes no sense to do so anyway. Reported-by: Eric Biggers Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto...") Signed-off-by: Herbert Xu Tested-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/pcrypt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'crypto') diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index 3e026e7a7e75..a4f3b3f342c8 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -71,7 +71,6 @@ static void pcrypt_aead_done(struct crypto_async_request *areq, int err) struct padata_priv *padata = pcrypt_request_padata(preq); padata->info = err; - req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; padata_do_serial(padata); } -- cgit v1.2.3 From 0a940d4e27658a545884351c46a70b132272a38d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:16:48 -0800 Subject: crypto: api - remove another reference to blkcipher Update a comment to refer to crypto_alloc_skcipher() rather than crypto_alloc_blkcipher() (the latter having been removed). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/api.c b/crypto/api.c index 55bca28df92d..4d3d13872fac 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -516,7 +516,7 @@ EXPORT_SYMBOL_GPL(crypto_find_alg); * * The returned transform is of a non-determinate type. Most people * should use one of the more specific allocation functions such as - * crypto_alloc_blkcipher. + * crypto_alloc_skcipher(). * * In case of error the return value is an error pointer. */ -- cgit v1.2.3 From 140734d3711335836cc1b9706d73953750fa4c8d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:03 -0800 Subject: crypto: skcipher - remove crypto_skcipher::ivsize Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher::ivsize is now redundant since it always equals crypto_skcipher_alg(tfm)->ivsize. Remove it and update crypto_skcipher_ivsize() accordingly. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 1 - 1 file changed, 1 deletion(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 13da43c84b64..7d2e722e82af 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -686,7 +686,6 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) skcipher->setkey = skcipher_setkey; skcipher->encrypt = alg->encrypt; skcipher->decrypt = alg->decrypt; - skcipher->ivsize = alg->ivsize; skcipher->keysize = alg->max_keysize; skcipher_set_needkey(skcipher); -- cgit v1.2.3 From 9ac0d136938ad8b8dd309f833abe5304dd2f0b08 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:04 -0800 Subject: crypto: skcipher - remove crypto_skcipher::keysize Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher::keysize is now redundant since it always equals crypto_skcipher_alg(tfm)->max_keysize. Remove it and update crypto_skcipher_default_keysize() accordingly. Also rename crypto_skcipher_default_keysize() to crypto_skcipher_max_keysize() to clarify that it specifically returns the maximum key size, not some unspecified "default". Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 3 +-- crypto/testmgr.c | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 7d2e722e82af..6cfafd80c7e6 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -585,7 +585,7 @@ static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg) static void skcipher_set_needkey(struct crypto_skcipher *tfm) { - if (tfm->keysize) + if (crypto_skcipher_max_keysize(tfm) != 0) crypto_skcipher_set_flags(tfm, CRYPTO_TFM_NEED_KEY); } @@ -686,7 +686,6 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) skcipher->setkey = skcipher_setkey; skcipher->encrypt = alg->encrypt; skcipher->decrypt = alg->decrypt; - skcipher->keysize = alg->max_keysize; skcipher_set_needkey(skcipher); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 82513b6b0abd..85d720a57bb0 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2647,7 +2647,7 @@ static void generate_random_cipher_testvec(struct skcipher_request *req, char *name, size_t max_namelen) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const unsigned int maxkeysize = tfm->keysize; + const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm); const unsigned int ivsize = crypto_skcipher_ivsize(tfm); struct scatterlist src, dst; u8 iv[MAX_IVLEN]; @@ -2693,6 +2693,7 @@ static int test_skcipher_vs_generic_impl(const char *driver, struct cipher_test_sglists *tsgls) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm); const unsigned int ivsize = crypto_skcipher_ivsize(tfm); const unsigned int blocksize = crypto_skcipher_blocksize(tfm); const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; @@ -2751,9 +2752,10 @@ static int test_skcipher_vs_generic_impl(const char *driver, /* Check the algorithm properties for consistency. */ - if (tfm->keysize != generic_tfm->keysize) { + if (maxkeysize != crypto_skcipher_max_keysize(generic_tfm)) { pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n", - driver, tfm->keysize, generic_tfm->keysize); + driver, maxkeysize, + crypto_skcipher_max_keysize(generic_tfm)); err = -EINVAL; goto out; } @@ -2778,7 +2780,7 @@ static int test_skcipher_vs_generic_impl(const char *driver, * the other implementation against them. */ - vec.key = kmalloc(tfm->keysize, GFP_KERNEL); + vec.key = kmalloc(maxkeysize, GFP_KERNEL); vec.iv = kmalloc(ivsize, GFP_KERNEL); vec.ptext = kmalloc(maxdatasize, GFP_KERNEL); vec.ctext = kmalloc(maxdatasize, GFP_KERNEL); -- cgit v1.2.3 From 15252d942739813c8d0eac4c1ee6d4c4eb6f101e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:05 -0800 Subject: crypto: skcipher - remove crypto_skcipher::setkey Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher::setkey now always points to skcipher_setkey(). Simplify by removing this function pointer and instead just making skcipher_setkey() be crypto_skcipher_setkey() directly. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 6cfafd80c7e6..4197b5ed57c4 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -610,7 +610,7 @@ static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm, return ret; } -static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, +int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { struct skcipher_alg *cipher = crypto_skcipher_alg(tfm); @@ -635,6 +635,7 @@ static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); return 0; } +EXPORT_SYMBOL_GPL(crypto_skcipher_setkey); int crypto_skcipher_encrypt(struct skcipher_request *req) { @@ -683,7 +684,6 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); - skcipher->setkey = skcipher_setkey; skcipher->encrypt = alg->encrypt; skcipher->decrypt = alg->decrypt; -- cgit v1.2.3 From 848755e315b61b0f939f6021e119373ff4a407ab Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:06 -0800 Subject: crypto: skcipher - remove crypto_skcipher::encrypt Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher::encrypt is now redundant since it always equals crypto_skcipher_alg(tfm)->encrypt. Remove it and update crypto_skcipher_encrypt() accordingly. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 4197b5ed57c4..926295ce1b07 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -648,7 +648,7 @@ int crypto_skcipher_encrypt(struct skcipher_request *req) if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ret = -ENOKEY; else - ret = tfm->encrypt(req); + ret = crypto_skcipher_alg(tfm)->encrypt(req); crypto_stats_skcipher_encrypt(cryptlen, ret, alg); return ret; } @@ -684,7 +684,6 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); - skcipher->encrypt = alg->encrypt; skcipher->decrypt = alg->decrypt; skcipher_set_needkey(skcipher); -- cgit v1.2.3 From 7e1c10991822de1c7a2d64647da56d96f430606c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:07 -0800 Subject: crypto: skcipher - remove crypto_skcipher::decrypt Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher::decrypt is now redundant since it always equals crypto_skcipher_alg(tfm)->decrypt. Remove it and update crypto_skcipher_decrypt() accordingly. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 926295ce1b07..e4e4a445dc66 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -665,7 +665,7 @@ int crypto_skcipher_decrypt(struct skcipher_request *req) if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ret = -ENOKEY; else - ret = tfm->decrypt(req); + ret = crypto_skcipher_alg(tfm)->decrypt(req); crypto_stats_skcipher_decrypt(cryptlen, ret, alg); return ret; } @@ -684,8 +684,6 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); - skcipher->decrypt = alg->decrypt; - skcipher_set_needkey(skcipher); if (alg->exit) -- cgit v1.2.3 From 89873b4411348325c5e513ea8086f0193eda5163 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 10:23:08 -0800 Subject: crypto: skcipher - remove crypto_skcipher_extsize() Due to the removal of the blkcipher and ablkcipher algorithm types, crypto_skcipher_extsize() now simply calls crypto_alg_extsize(). So remove it and just use crypto_alg_extsize(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index e4e4a445dc66..39a718d99220 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -578,11 +578,6 @@ int skcipher_walk_aead_decrypt(struct skcipher_walk *walk, } EXPORT_SYMBOL_GPL(skcipher_walk_aead_decrypt); -static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg) -{ - return crypto_alg_extsize(alg); -} - static void skcipher_set_needkey(struct crypto_skcipher *tfm) { if (crypto_skcipher_max_keysize(tfm) != 0) @@ -749,7 +744,7 @@ static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg) #endif static const struct crypto_type crypto_skcipher_type = { - .extsize = crypto_skcipher_extsize, + .extsize = crypto_alg_extsize, .init_tfm = crypto_skcipher_init_tfm, .free = crypto_skcipher_free_instance, #ifdef CONFIG_PROC_FS -- cgit v1.2.3 From c28817895464797a8299b24e35ead1085b3e40fb Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Nov 2019 11:35:22 -0800 Subject: crypto: shash - allow essiv and hmac to use OPTIONAL_KEY algorithms The essiv and hmac templates refuse to use any hash algorithm that has a ->setkey() function, which includes not just algorithms that always need a key, but also algorithms that optionally take a key. Previously the only optionally-keyed hash algorithms in the crypto API were non-cryptographic algorithms like crc32, so this didn't really matter. But that's changed with BLAKE2 support being added. BLAKE2 should work with essiv and hmac, just like any other cryptographic hash. Fix this by allowing the use of both algorithms without a ->setkey() function and algorithms that have the OPTIONAL_KEY flag set. Signed-off-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/essiv.c | 2 +- crypto/hmac.c | 4 ++-- crypto/shash.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/essiv.c b/crypto/essiv.c index 808f2b362106..e4b32c2ea7ec 100644 --- a/crypto/essiv.c +++ b/crypto/essiv.c @@ -442,7 +442,7 @@ static bool essiv_supported_algorithms(const char *essiv_cipher_name, if (ivsize != alg->cra_blocksize) goto out; - if (crypto_shash_alg_has_setkey(hash_alg)) + if (crypto_shash_alg_needs_key(hash_alg)) goto out; ret = true; diff --git a/crypto/hmac.c b/crypto/hmac.c index 8b2a212eb0ad..377f07733e2f 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -185,9 +185,9 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) return PTR_ERR(salg); alg = &salg->base; - /* The underlying hash algorithm must be unkeyed */ + /* The underlying hash algorithm must not require a key */ err = -EINVAL; - if (crypto_shash_alg_has_setkey(salg)) + if (crypto_shash_alg_needs_key(salg)) goto out_put_alg; ds = salg->digestsize; diff --git a/crypto/shash.c b/crypto/shash.c index e83c5124f6eb..7989258a46b4 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -50,8 +50,7 @@ static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg) { - if (crypto_shash_alg_has_setkey(alg) && - !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) + if (crypto_shash_alg_needs_key(alg)) crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY); } -- cgit v1.2.3 From eb455dbd02cb1074b37872ffca30a81cb2a18eaa Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Dec 2019 13:53:26 -0800 Subject: crypto: testmgr - don't try to decrypt uninitialized buffers Currently if the comparison fuzz tests encounter an encryption error when generating an skcipher or AEAD test vector, they will still test the decryption side (passing it the uninitialized ciphertext buffer) and expect it to fail with the same error. This is sort of broken because it's not well-defined usage of the API to pass an uninitialized buffer, and furthermore in the AEAD case it's acceptable for the decryption error to be EBADMSG (meaning "inauthentic input") even if the encryption error was something else like EINVAL. Fix this for skcipher by explicitly initializing the ciphertext buffer on error, and for AEAD by skipping the decryption test on error. Reported-by: Pascal Van Leeuwen Fixes: d435e10e67be ("crypto: testmgr - fuzz skciphers against their generic implementation") Fixes: 40153b10d91c ("crypto: testmgr - fuzz AEADs against their generic implementation") Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 85d720a57bb0..a8940415512f 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2102,6 +2102,7 @@ static void generate_random_aead_testvec(struct aead_request *req, * If the key or authentication tag size couldn't be set, no need to * continue to encrypt. */ + vec->crypt_error = 0; if (vec->setkey_error || vec->setauthsize_error) goto done; @@ -2245,10 +2246,12 @@ static int test_aead_vs_generic_impl(const char *driver, req, tsgls); if (err) goto out; - err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, cfg, - req, tsgls); - if (err) - goto out; + if (vec.crypt_error == 0) { + err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, + cfg, req, tsgls); + if (err) + goto out; + } cond_resched(); } err = 0; @@ -2678,6 +2681,15 @@ static void generate_random_cipher_testvec(struct skcipher_request *req, skcipher_request_set_callback(req, 0, crypto_req_done, &wait); skcipher_request_set_crypt(req, &src, &dst, vec->len, iv); vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); + if (vec->crypt_error != 0) { + /* + * The only acceptable error here is for an invalid length, so + * skcipher decryption should fail with the same error too. + * We'll test for this. But to keep the API usage well-defined, + * explicitly initialize the ciphertext buffer too. + */ + memset((u8 *)vec->ctext, 0, vec->len); + } done: snprintf(name, max_namelen, "\"random: len=%u klen=%u\"", vec->len, vec->klen); -- cgit v1.2.3 From fd60f727876467a89ac42c873e20b38d9a408062 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Dec 2019 13:53:27 -0800 Subject: crypto: testmgr - check skcipher min_keysize When checking two implementations of the same skcipher algorithm for consistency, require that the minimum key size be the same, not just the maximum key size. There's no good reason to allow different minimum key sizes. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index a8940415512f..3d7c1c1529cf 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2764,6 +2764,15 @@ static int test_skcipher_vs_generic_impl(const char *driver, /* Check the algorithm properties for consistency. */ + if (crypto_skcipher_min_keysize(tfm) != + crypto_skcipher_min_keysize(generic_tfm)) { + pr_err("alg: skcipher: min keysize for %s (%u) doesn't match generic impl (%u)\n", + driver, crypto_skcipher_min_keysize(tfm), + crypto_skcipher_min_keysize(generic_tfm)); + err = -EINVAL; + goto out; + } + if (maxkeysize != crypto_skcipher_max_keysize(generic_tfm)) { pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n", driver, maxkeysize, -- cgit v1.2.3 From fd8c37c72d60c7c8f5c4d0702a0b30499cf9d422 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Dec 2019 13:53:28 -0800 Subject: crypto: testmgr - test setting misaligned keys The alignment bug in ghash_setkey() fixed by commit 5c6bc4dfa515 ("crypto: ghash - fix unaligned memory access in ghash_setkey()") wasn't reliably detected by the crypto self-tests on ARM because the tests only set the keys directly from the test vectors. To improve test coverage, update the tests to sometimes pass misaligned keys to setkey(). This applies to shash, ahash, skcipher, and aead. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 3d7c1c1529cf..d1ffa8f73948 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -259,6 +259,9 @@ struct test_sg_division { * where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to * the @iv_offset + * @key_offset: misalignment of the key, where 0 is default alignment + * @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to + * the @key_offset * @finalization_type: what finalization function to use for hashes * @nosimd: execute with SIMD disabled? Requires !CRYPTO_TFM_REQ_MAY_SLEEP. */ @@ -269,7 +272,9 @@ struct testvec_config { struct test_sg_division src_divs[XBUFSIZE]; struct test_sg_division dst_divs[XBUFSIZE]; unsigned int iv_offset; + unsigned int key_offset; bool iv_offset_relative_to_alignmask; + bool key_offset_relative_to_alignmask; enum finalization_type finalization_type; bool nosimd; }; @@ -297,6 +302,7 @@ static const struct testvec_config default_cipher_testvec_configs[] = { .name = "unaligned buffer, offset=1", .src_divs = { { .proportion_of_total = 10000, .offset = 1 } }, .iv_offset = 1, + .key_offset = 1, }, { .name = "buffer aligned only to alignmask", .src_divs = { @@ -308,6 +314,8 @@ static const struct testvec_config default_cipher_testvec_configs[] = { }, .iv_offset = 1, .iv_offset_relative_to_alignmask = true, + .key_offset = 1, + .key_offset_relative_to_alignmask = true, }, { .name = "two even aligned splits", .src_divs = { @@ -323,6 +331,7 @@ static const struct testvec_config default_cipher_testvec_configs[] = { { .proportion_of_total = 4800, .offset = 18 }, }, .iv_offset = 3, + .key_offset = 3, }, { .name = "misaligned splits crossing pages, inplace", .inplace = true, @@ -355,6 +364,7 @@ static const struct testvec_config default_hash_testvec_configs[] = { .name = "init+update+final misaligned buffer", .src_divs = { { .proportion_of_total = 10000, .offset = 1 } }, .finalization_type = FINALIZATION_TYPE_FINAL, + .key_offset = 1, }, { .name = "digest buffer aligned only to alignmask", .src_divs = { @@ -365,6 +375,8 @@ static const struct testvec_config default_hash_testvec_configs[] = { }, }, .finalization_type = FINALIZATION_TYPE_DIGEST, + .key_offset = 1, + .key_offset_relative_to_alignmask = true, }, { .name = "init+update+update+final two even splits", .src_divs = { @@ -740,6 +752,49 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls, alignmask, dst_total_len, NULL, NULL); } +/* + * Support for testing passing a misaligned key to setkey(): + * + * If cfg->key_offset is set, copy the key into a new buffer at that offset, + * optionally adding alignmask. Else, just use the key directly. + */ +static int prepare_keybuf(const u8 *key, unsigned int ksize, + const struct testvec_config *cfg, + unsigned int alignmask, + const u8 **keybuf_ret, const u8 **keyptr_ret) +{ + unsigned int key_offset = cfg->key_offset; + u8 *keybuf = NULL, *keyptr = (u8 *)key; + + if (key_offset != 0) { + if (cfg->key_offset_relative_to_alignmask) + key_offset += alignmask; + keybuf = kmalloc(key_offset + ksize, GFP_KERNEL); + if (!keybuf) + return -ENOMEM; + keyptr = keybuf + key_offset; + memcpy(keyptr, key, ksize); + } + *keybuf_ret = keybuf; + *keyptr_ret = keyptr; + return 0; +} + +/* Like setkey_f(tfm, key, ksize), but sometimes misalign the key */ +#define do_setkey(setkey_f, tfm, key, ksize, cfg, alignmask) \ +({ \ + const u8 *keybuf, *keyptr; \ + int err; \ + \ + err = prepare_keybuf((key), (ksize), (cfg), (alignmask), \ + &keybuf, &keyptr); \ + if (err == 0) { \ + err = setkey_f((tfm), keyptr, (ksize)); \ + kfree(keybuf); \ + } \ + err; \ +}) + #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS /* Generate a random length in range [0, max_len], but prefer smaller values */ @@ -966,6 +1021,11 @@ static void generate_random_testvec_config(struct testvec_config *cfg, p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset); } + if (prandom_u32() % 2 == 0) { + cfg->key_offset = 1 + (prandom_u32() % MAX_ALGAPI_ALIGNMASK); + p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset); + } + WARN_ON_ONCE(!valid_testvec_config(cfg)); } @@ -1103,7 +1163,8 @@ static int test_shash_vec_cfg(const char *driver, /* Set the key, if specified */ if (vec->ksize) { - err = crypto_shash_setkey(tfm, vec->key, vec->ksize); + err = do_setkey(crypto_shash_setkey, tfm, vec->key, vec->ksize, + cfg, alignmask); if (err) { if (err == vec->setkey_error) return 0; @@ -1290,7 +1351,8 @@ static int test_ahash_vec_cfg(const char *driver, /* Set the key, if specified */ if (vec->ksize) { - err = crypto_ahash_setkey(tfm, vec->key, vec->ksize); + err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize, + cfg, alignmask); if (err) { if (err == vec->setkey_error) return 0; @@ -1861,7 +1923,9 @@ static int test_aead_vec_cfg(const char *driver, int enc, crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); else crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); - err = crypto_aead_setkey(tfm, vec->key, vec->klen); + + err = do_setkey(crypto_aead_setkey, tfm, vec->key, vec->klen, + cfg, alignmask); if (err && err != vec->setkey_error) { pr_err("alg: aead: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", driver, vec_name, vec->setkey_error, err, @@ -2460,7 +2524,8 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, else crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); - err = crypto_skcipher_setkey(tfm, vec->key, vec->klen); + err = do_setkey(crypto_skcipher_setkey, tfm, vec->key, vec->klen, + cfg, alignmask); if (err) { if (err == vec->setkey_error) return 0; -- cgit v1.2.3 From 2ea915054cf2dc1ccc145d7c75d3dad8dde15be3 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Dec 2019 13:53:29 -0800 Subject: crypto: testmgr - create struct aead_extra_tests_ctx In preparation for adding inauthentic input fuzz tests, which don't require that a generic implementation of the algorithm be available, refactor test_aead_vs_generic_impl() so that instead there's a higher-level function test_aead_extra() which initializes a struct aead_extra_tests_ctx and then calls test_aead_vs_generic_impl() with a pointer to that struct. As a bonus, this reduces stack usage. Also switch from crypto_aead_alg(tfm)->maxauthsize to crypto_aead_maxauthsize(), now that the latter is available in . Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 170 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 71 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d1ffa8f73948..4fe210845e78 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2111,6 +2111,22 @@ static int test_aead_vec(const char *driver, int enc, } #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS + +struct aead_extra_tests_ctx { + struct aead_request *req; + struct crypto_aead *tfm; + const char *driver; + const struct alg_test_desc *test_desc; + struct cipher_test_sglists *tsgls; + unsigned int maxdatasize; + unsigned int maxkeysize; + + struct aead_testvec vec; + char vec_name[64]; + char cfgname[TESTVEC_CONFIG_NAMELEN]; + struct testvec_config cfg; +}; + /* * Generate an AEAD test vector from the given implementation. * Assumes the buffers in 'vec' were already allocated. @@ -2123,7 +2139,7 @@ static void generate_random_aead_testvec(struct aead_request *req, { struct crypto_aead *tfm = crypto_aead_reqtfm(req); const unsigned int ivsize = crypto_aead_ivsize(tfm); - unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize; + const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm); unsigned int authsize; unsigned int total_len; int i; @@ -2192,35 +2208,21 @@ done: } /* - * Test the AEAD algorithm represented by @req against the corresponding generic - * implementation, if one is available. + * Test the AEAD algorithm against the corresponding generic implementation, if + * one is available. */ -static int test_aead_vs_generic_impl(const char *driver, - const struct alg_test_desc *test_desc, - struct aead_request *req, - struct cipher_test_sglists *tsgls) +static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx) { - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - const unsigned int ivsize = crypto_aead_ivsize(tfm); - const unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize; - const unsigned int blocksize = crypto_aead_blocksize(tfm); - const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; + struct crypto_aead *tfm = ctx->tfm; const char *algname = crypto_aead_alg(tfm)->base.cra_name; - const char *generic_driver = test_desc->generic_driver; + const char *driver = ctx->driver; + const char *generic_driver = ctx->test_desc->generic_driver; char _generic_driver[CRYPTO_MAX_ALG_NAME]; struct crypto_aead *generic_tfm = NULL; struct aead_request *generic_req = NULL; - unsigned int maxkeysize; unsigned int i; - struct aead_testvec vec = { 0 }; - char vec_name[64]; - struct testvec_config *cfg; - char cfgname[TESTVEC_CONFIG_NAMELEN]; int err; - if (noextratests) - return 0; - if (!generic_driver) { /* Use default naming convention? */ err = build_generic_driver_name(algname, _generic_driver); if (err) @@ -2244,12 +2246,6 @@ static int test_aead_vs_generic_impl(const char *driver, return err; } - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) { - err = -ENOMEM; - goto out; - } - generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL); if (!generic_req) { err = -ENOMEM; @@ -2258,24 +2254,27 @@ static int test_aead_vs_generic_impl(const char *driver, /* Check the algorithm properties for consistency. */ - if (maxauthsize != crypto_aead_alg(generic_tfm)->maxauthsize) { + if (crypto_aead_maxauthsize(tfm) != + crypto_aead_maxauthsize(generic_tfm)) { pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n", - driver, maxauthsize, - crypto_aead_alg(generic_tfm)->maxauthsize); + driver, crypto_aead_maxauthsize(tfm), + crypto_aead_maxauthsize(generic_tfm)); err = -EINVAL; goto out; } - if (ivsize != crypto_aead_ivsize(generic_tfm)) { + if (crypto_aead_ivsize(tfm) != crypto_aead_ivsize(generic_tfm)) { pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n", - driver, ivsize, crypto_aead_ivsize(generic_tfm)); + driver, crypto_aead_ivsize(tfm), + crypto_aead_ivsize(generic_tfm)); err = -EINVAL; goto out; } - if (blocksize != crypto_aead_blocksize(generic_tfm)) { + if (crypto_aead_blocksize(tfm) != crypto_aead_blocksize(generic_tfm)) { pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n", - driver, blocksize, crypto_aead_blocksize(generic_tfm)); + driver, crypto_aead_blocksize(tfm), + crypto_aead_blocksize(generic_tfm)); err = -EINVAL; goto out; } @@ -2284,35 +2283,22 @@ static int test_aead_vs_generic_impl(const char *driver, * Now generate test vectors using the generic implementation, and test * the other implementation against them. */ - - maxkeysize = 0; - for (i = 0; i < test_desc->suite.aead.count; i++) - maxkeysize = max_t(unsigned int, maxkeysize, - test_desc->suite.aead.vecs[i].klen); - - vec.key = kmalloc(maxkeysize, GFP_KERNEL); - vec.iv = kmalloc(ivsize, GFP_KERNEL); - vec.assoc = kmalloc(maxdatasize, GFP_KERNEL); - vec.ptext = kmalloc(maxdatasize, GFP_KERNEL); - vec.ctext = kmalloc(maxdatasize, GFP_KERNEL); - if (!vec.key || !vec.iv || !vec.assoc || !vec.ptext || !vec.ctext) { - err = -ENOMEM; - goto out; - } - for (i = 0; i < fuzz_iterations * 8; i++) { - generate_random_aead_testvec(generic_req, &vec, - maxkeysize, maxdatasize, - vec_name, sizeof(vec_name)); - generate_random_testvec_config(cfg, cfgname, sizeof(cfgname)); - - err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, cfg, - req, tsgls); + generate_random_aead_testvec(generic_req, &ctx->vec, + ctx->maxkeysize, ctx->maxdatasize, + ctx->vec_name, + sizeof(ctx->vec_name)); + generate_random_testvec_config(&ctx->cfg, ctx->cfgname, + sizeof(ctx->cfgname)); + err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec, + ctx->vec_name, &ctx->cfg, + ctx->req, ctx->tsgls); if (err) goto out; - if (vec.crypt_error == 0) { - err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, - cfg, req, tsgls); + if (ctx->vec.crypt_error == 0) { + err = test_aead_vec_cfg(driver, DECRYPT, &ctx->vec, + ctx->vec_name, &ctx->cfg, + ctx->req, ctx->tsgls); if (err) goto out; } @@ -2320,21 +2306,63 @@ static int test_aead_vs_generic_impl(const char *driver, } err = 0; out: - kfree(cfg); - kfree(vec.key); - kfree(vec.iv); - kfree(vec.assoc); - kfree(vec.ptext); - kfree(vec.ctext); crypto_free_aead(generic_tfm); aead_request_free(generic_req); return err; } + +static int test_aead_extra(const char *driver, + const struct alg_test_desc *test_desc, + struct aead_request *req, + struct cipher_test_sglists *tsgls) +{ + struct aead_extra_tests_ctx *ctx; + unsigned int i; + int err; + + if (noextratests) + return 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->req = req; + ctx->tfm = crypto_aead_reqtfm(req); + ctx->driver = driver; + ctx->test_desc = test_desc; + ctx->tsgls = tsgls; + ctx->maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; + ctx->maxkeysize = 0; + for (i = 0; i < test_desc->suite.aead.count; i++) + ctx->maxkeysize = max_t(unsigned int, ctx->maxkeysize, + test_desc->suite.aead.vecs[i].klen); + + ctx->vec.key = kmalloc(ctx->maxkeysize, GFP_KERNEL); + ctx->vec.iv = kmalloc(crypto_aead_ivsize(ctx->tfm), GFP_KERNEL); + ctx->vec.assoc = kmalloc(ctx->maxdatasize, GFP_KERNEL); + ctx->vec.ptext = kmalloc(ctx->maxdatasize, GFP_KERNEL); + ctx->vec.ctext = kmalloc(ctx->maxdatasize, GFP_KERNEL); + if (!ctx->vec.key || !ctx->vec.iv || !ctx->vec.assoc || + !ctx->vec.ptext || !ctx->vec.ctext) { + err = -ENOMEM; + goto out; + } + + err = test_aead_vs_generic_impl(ctx); +out: + kfree(ctx->vec.key); + kfree(ctx->vec.iv); + kfree(ctx->vec.assoc); + kfree(ctx->vec.ptext); + kfree(ctx->vec.ctext); + kfree(ctx); + return err; +} #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ -static int test_aead_vs_generic_impl(const char *driver, - const struct alg_test_desc *test_desc, - struct aead_request *req, - struct cipher_test_sglists *tsgls) +static int test_aead_extra(const char *driver, + const struct alg_test_desc *test_desc, + struct aead_request *req, + struct cipher_test_sglists *tsgls) { return 0; } @@ -2403,7 +2431,7 @@ static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, if (err) goto out; - err = test_aead_vs_generic_impl(driver, desc, req, tsgls); + err = test_aead_extra(driver, desc, req, tsgls); out: free_cipher_test_sglists(tsgls); aead_request_free(req); -- cgit v1.2.3 From 49763fc6b1af422e742e58fd04e078ab011edd96 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 1 Dec 2019 13:53:30 -0800 Subject: crypto: testmgr - generate inauthentic AEAD test vectors The whole point of using an AEAD over length-preserving encryption is that the data is authenticated. However currently the fuzz tests don't test any inauthentic inputs to verify that the data is actually being authenticated. And only two algorithms ("rfc4543(gcm(aes))" and "ccm(aes)") even have any inauthentic test vectors at all. Therefore, update the AEAD fuzz tests to sometimes generate inauthentic test vectors, either by generating a (ciphertext, AAD) pair without using the key, or by mutating an authentic pair that was generated. To avoid flakiness, only assume this works reliably if the auth tag is at least 8 bytes. Also account for the rfc4106, rfc4309, and rfc7539esp algorithms intentionally ignoring the last 8 AAD bytes, and for some algorithms doing extra checks that result in EINVAL rather than EBADMSG. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 320 +++++++++++++++++++++++++++++++++++++++++++------------ crypto/testmgr.h | 14 ++- 2 files changed, 261 insertions(+), 73 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4fe210845e78..88f33c0efb23 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -82,6 +82,19 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) struct aead_test_suite { const struct aead_testvec *vecs; unsigned int count; + + /* + * Set if trying to decrypt an inauthentic ciphertext with this + * algorithm might result in EINVAL rather than EBADMSG, due to other + * validation the algorithm does on the inputs such as length checks. + */ + unsigned int einval_allowed : 1; + + /* + * Set if the algorithm intentionally ignores the last 8 bytes of the + * AAD buffer during decryption. + */ + unsigned int esp_aad : 1; }; struct cipher_test_suite { @@ -814,27 +827,39 @@ static unsigned int generate_random_length(unsigned int max_len) } } -/* Sometimes make some random changes to the given data buffer */ -static void mutate_buffer(u8 *buf, size_t count) +/* Flip a random bit in the given nonempty data buffer */ +static void flip_random_bit(u8 *buf, size_t size) +{ + size_t bitpos; + + bitpos = prandom_u32() % (size * 8); + buf[bitpos / 8] ^= 1 << (bitpos % 8); +} + +/* Flip a random byte in the given nonempty data buffer */ +static void flip_random_byte(u8 *buf, size_t size) +{ + buf[prandom_u32() % size] ^= 0xff; +} + +/* Sometimes make some random changes to the given nonempty data buffer */ +static void mutate_buffer(u8 *buf, size_t size) { size_t num_flips; size_t i; - size_t pos; /* Sometimes flip some bits */ if (prandom_u32() % 4 == 0) { - num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count * 8); - for (i = 0; i < num_flips; i++) { - pos = prandom_u32() % (count * 8); - buf[pos / 8] ^= 1 << (pos % 8); - } + num_flips = min_t(size_t, 1 << (prandom_u32() % 8), size * 8); + for (i = 0; i < num_flips; i++) + flip_random_bit(buf, size); } /* Sometimes flip some bytes */ if (prandom_u32() % 4 == 0) { - num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count); + num_flips = min_t(size_t, 1 << (prandom_u32() % 8), size); for (i = 0; i < num_flips; i++) - buf[prandom_u32() % count] ^= 0xff; + flip_random_byte(buf, size); } } @@ -1915,7 +1940,6 @@ static int test_aead_vec_cfg(const char *driver, int enc, cfg->iv_offset + (cfg->iv_offset_relative_to_alignmask ? alignmask : 0); struct kvec input[2]; - int expected_error; int err; /* Set the key */ @@ -2036,20 +2060,31 @@ static int test_aead_vec_cfg(const char *driver, int enc, return -EINVAL; } - /* Check for success or failure */ - expected_error = vec->novrfy ? -EBADMSG : vec->crypt_error; - if (err) { - if (err == expected_error) - return 0; - pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", - driver, op, vec_name, expected_error, err, cfg->name); - return err; - } - if (expected_error) { - pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", + /* Check for unexpected success or failure, or wrong error code */ + if ((err == 0 && vec->novrfy) || + (err != vec->crypt_error && !(err == -EBADMSG && vec->novrfy))) { + char expected_error[32]; + + if (vec->novrfy && + vec->crypt_error != 0 && vec->crypt_error != -EBADMSG) + sprintf(expected_error, "-EBADMSG or %d", + vec->crypt_error); + else if (vec->novrfy) + sprintf(expected_error, "-EBADMSG"); + else + sprintf(expected_error, "%d", vec->crypt_error); + if (err) { + pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%s, actual_error=%d, cfg=\"%s\"\n", + driver, op, vec_name, expected_error, err, + cfg->name); + return err; + } + pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%s, cfg=\"%s\"\n", driver, op, vec_name, expected_error, cfg->name); return -EINVAL; } + if (err) /* Expectedly failed. */ + return 0; /* Check for the correct output (ciphertext or plaintext) */ err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, @@ -2128,24 +2163,112 @@ struct aead_extra_tests_ctx { }; /* - * Generate an AEAD test vector from the given implementation. - * Assumes the buffers in 'vec' were already allocated. + * Make at least one random change to a (ciphertext, AAD) pair. "Ciphertext" + * here means the full ciphertext including the authentication tag. The + * authentication tag (and hence also the ciphertext) is assumed to be nonempty. + */ +static void mutate_aead_message(struct aead_testvec *vec, bool esp_aad) +{ + const unsigned int aad_tail_size = esp_aad ? 8 : 0; + const unsigned int authsize = vec->clen - vec->plen; + + if (prandom_u32() % 2 == 0 && vec->alen > aad_tail_size) { + /* Mutate the AAD */ + flip_random_bit((u8 *)vec->assoc, vec->alen - aad_tail_size); + if (prandom_u32() % 2 == 0) + return; + } + if (prandom_u32() % 2 == 0) { + /* Mutate auth tag (assuming it's at the end of ciphertext) */ + flip_random_bit((u8 *)vec->ctext + vec->plen, authsize); + } else { + /* Mutate any part of the ciphertext */ + flip_random_bit((u8 *)vec->ctext, vec->clen); + } +} + +/* + * Minimum authentication tag size in bytes at which we assume that we can + * reliably generate inauthentic messages, i.e. not generate an authentic + * message by chance. + */ +#define MIN_COLLISION_FREE_AUTHSIZE 8 + +static void generate_aead_message(struct aead_request *req, + const struct aead_test_suite *suite, + struct aead_testvec *vec, + bool prefer_inauthentic) +{ + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + const unsigned int ivsize = crypto_aead_ivsize(tfm); + const unsigned int authsize = vec->clen - vec->plen; + const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) && + (prefer_inauthentic || prandom_u32() % 4 == 0); + + /* Generate the AAD. */ + generate_random_bytes((u8 *)vec->assoc, vec->alen); + + if (inauthentic && prandom_u32() % 2 == 0) { + /* Generate a random ciphertext. */ + generate_random_bytes((u8 *)vec->ctext, vec->clen); + } else { + int i = 0; + struct scatterlist src[2], dst; + u8 iv[MAX_IVLEN]; + DECLARE_CRYPTO_WAIT(wait); + + /* Generate a random plaintext and encrypt it. */ + sg_init_table(src, 2); + if (vec->alen) + sg_set_buf(&src[i++], vec->assoc, vec->alen); + if (vec->plen) { + generate_random_bytes((u8 *)vec->ptext, vec->plen); + sg_set_buf(&src[i++], vec->ptext, vec->plen); + } + sg_init_one(&dst, vec->ctext, vec->alen + vec->clen); + memcpy(iv, vec->iv, ivsize); + aead_request_set_callback(req, 0, crypto_req_done, &wait); + aead_request_set_crypt(req, src, &dst, vec->plen, iv); + aead_request_set_ad(req, vec->alen); + vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req), + &wait); + /* If encryption failed, we're done. */ + if (vec->crypt_error != 0) + return; + memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen); + if (!inauthentic) + return; + /* + * Mutate the authentic (ciphertext, AAD) pair to get an + * inauthentic one. + */ + mutate_aead_message(vec, suite->esp_aad); + } + vec->novrfy = 1; + if (suite->einval_allowed) + vec->crypt_error = -EINVAL; +} + +/* + * Generate an AEAD test vector 'vec' using the implementation specified by + * 'req'. The buffers in 'vec' must already be allocated. + * + * If 'prefer_inauthentic' is true, then this function will generate inauthentic + * test vectors (i.e. vectors with 'vec->novrfy=1') more often. */ static void generate_random_aead_testvec(struct aead_request *req, struct aead_testvec *vec, + const struct aead_test_suite *suite, unsigned int maxkeysize, unsigned int maxdatasize, - char *name, size_t max_namelen) + char *name, size_t max_namelen, + bool prefer_inauthentic) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); const unsigned int ivsize = crypto_aead_ivsize(tfm); const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm); unsigned int authsize; unsigned int total_len; - int i; - struct scatterlist src[2], dst; - u8 iv[MAX_IVLEN]; - DECLARE_CRYPTO_WAIT(wait); /* Key: length in [0, maxkeysize], but usually choose maxkeysize */ vec->klen = maxkeysize; @@ -2161,50 +2284,83 @@ static void generate_random_aead_testvec(struct aead_request *req, authsize = maxauthsize; if (prandom_u32() % 4 == 0) authsize = prandom_u32() % (maxauthsize + 1); + if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE) + authsize = MIN_COLLISION_FREE_AUTHSIZE; if (WARN_ON(authsize > maxdatasize)) authsize = maxdatasize; maxdatasize -= authsize; vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize); - /* Plaintext and associated data */ + /* AAD, plaintext, and ciphertext lengths */ total_len = generate_random_length(maxdatasize); if (prandom_u32() % 4 == 0) vec->alen = 0; else vec->alen = generate_random_length(total_len); vec->plen = total_len - vec->alen; - generate_random_bytes((u8 *)vec->assoc, vec->alen); - generate_random_bytes((u8 *)vec->ptext, vec->plen); - vec->clen = vec->plen + authsize; /* - * If the key or authentication tag size couldn't be set, no need to - * continue to encrypt. + * Generate the AAD, plaintext, and ciphertext. Not applicable if the + * key or the authentication tag size couldn't be set. */ + vec->novrfy = 0; vec->crypt_error = 0; - if (vec->setkey_error || vec->setauthsize_error) - goto done; - - /* Ciphertext */ - sg_init_table(src, 2); - i = 0; - if (vec->alen) - sg_set_buf(&src[i++], vec->assoc, vec->alen); - if (vec->plen) - sg_set_buf(&src[i++], vec->ptext, vec->plen); - sg_init_one(&dst, vec->ctext, vec->alen + vec->clen); - memcpy(iv, vec->iv, ivsize); - aead_request_set_callback(req, 0, crypto_req_done, &wait); - aead_request_set_crypt(req, src, &dst, vec->plen, iv); - aead_request_set_ad(req, vec->alen); - vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req), &wait); - if (vec->crypt_error == 0) - memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen); -done: + if (vec->setkey_error == 0 && vec->setauthsize_error == 0) + generate_aead_message(req, suite, vec, prefer_inauthentic); snprintf(name, max_namelen, - "\"random: alen=%u plen=%u authsize=%u klen=%u\"", - vec->alen, vec->plen, authsize, vec->klen); + "\"random: alen=%u plen=%u authsize=%u klen=%u novrfy=%d\"", + vec->alen, vec->plen, authsize, vec->klen, vec->novrfy); +} + +static void try_to_generate_inauthentic_testvec( + struct aead_extra_tests_ctx *ctx) +{ + int i; + + for (i = 0; i < 10; i++) { + generate_random_aead_testvec(ctx->req, &ctx->vec, + &ctx->test_desc->suite.aead, + ctx->maxkeysize, ctx->maxdatasize, + ctx->vec_name, + sizeof(ctx->vec_name), true); + if (ctx->vec.novrfy) + return; + } +} + +/* + * Generate inauthentic test vectors (i.e. ciphertext, AAD pairs that aren't the + * result of an encryption with the key) and verify that decryption fails. + */ +static int test_aead_inauthentic_inputs(struct aead_extra_tests_ctx *ctx) +{ + unsigned int i; + int err; + + for (i = 0; i < fuzz_iterations * 8; i++) { + /* + * Since this part of the tests isn't comparing the + * implementation to another, there's no point in testing any + * test vectors other than inauthentic ones (vec.novrfy=1) here. + * + * If we're having trouble generating such a test vector, e.g. + * if the algorithm keeps rejecting the generated keys, don't + * retry forever; just continue on. + */ + try_to_generate_inauthentic_testvec(ctx); + if (ctx->vec.novrfy) { + generate_random_testvec_config(&ctx->cfg, ctx->cfgname, + sizeof(ctx->cfgname)); + err = test_aead_vec_cfg(ctx->driver, DECRYPT, &ctx->vec, + ctx->vec_name, &ctx->cfg, + ctx->req, ctx->tsgls); + if (err) + return err; + } + cond_resched(); + } + return 0; } /* @@ -2285,17 +2441,20 @@ static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx) */ for (i = 0; i < fuzz_iterations * 8; i++) { generate_random_aead_testvec(generic_req, &ctx->vec, + &ctx->test_desc->suite.aead, ctx->maxkeysize, ctx->maxdatasize, ctx->vec_name, - sizeof(ctx->vec_name)); + sizeof(ctx->vec_name), false); generate_random_testvec_config(&ctx->cfg, ctx->cfgname, sizeof(ctx->cfgname)); - err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec, - ctx->vec_name, &ctx->cfg, - ctx->req, ctx->tsgls); - if (err) - goto out; - if (ctx->vec.crypt_error == 0) { + if (!ctx->vec.novrfy) { + err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec, + ctx->vec_name, &ctx->cfg, + ctx->req, ctx->tsgls); + if (err) + goto out; + } + if (ctx->vec.crypt_error == 0 || ctx->vec.novrfy) { err = test_aead_vec_cfg(driver, DECRYPT, &ctx->vec, ctx->vec_name, &ctx->cfg, ctx->req, ctx->tsgls); @@ -2348,6 +2507,10 @@ static int test_aead_extra(const char *driver, goto out; } + err = test_aead_inauthentic_inputs(ctx); + if (err) + goto out; + err = test_aead_vs_generic_impl(ctx); out: kfree(ctx->vec.key); @@ -3978,7 +4141,8 @@ static int alg_test_null(const struct alg_test_desc *desc, return 0; } -#define __VECS(tv) { .vecs = tv, .count = ARRAY_SIZE(tv) } +#define ____VECS(tv) .vecs = tv, .count = ARRAY_SIZE(tv) +#define __VECS(tv) { ____VECS(tv) } /* Please keep this list sorted by algorithm name. */ static const struct alg_test_desc alg_test_descs[] = { @@ -4284,7 +4448,10 @@ static const struct alg_test_desc alg_test_descs[] = { .test = alg_test_aead, .fips_allowed = 1, .suite = { - .aead = __VECS(aes_ccm_tv_template) + .aead = { + ____VECS(aes_ccm_tv_template), + .einval_allowed = 1, + } } }, { .alg = "cfb(aes)", @@ -5032,7 +5199,11 @@ static const struct alg_test_desc alg_test_descs[] = { .test = alg_test_aead, .fips_allowed = 1, .suite = { - .aead = __VECS(aes_gcm_rfc4106_tv_template) + .aead = { + ____VECS(aes_gcm_rfc4106_tv_template), + .einval_allowed = 1, + .esp_aad = 1, + } } }, { .alg = "rfc4309(ccm(aes))", @@ -5040,14 +5211,21 @@ static const struct alg_test_desc alg_test_descs[] = { .test = alg_test_aead, .fips_allowed = 1, .suite = { - .aead = __VECS(aes_ccm_rfc4309_tv_template) + .aead = { + ____VECS(aes_ccm_rfc4309_tv_template), + .einval_allowed = 1, + .esp_aad = 1, + } } }, { .alg = "rfc4543(gcm(aes))", .generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))", .test = alg_test_aead, .suite = { - .aead = __VECS(aes_gcm_rfc4543_tv_template) + .aead = { + ____VECS(aes_gcm_rfc4543_tv_template), + .einval_allowed = 1, + } } }, { .alg = "rfc7539(chacha20,poly1305)", @@ -5059,7 +5237,11 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "rfc7539esp(chacha20,poly1305)", .test = alg_test_aead, .suite = { - .aead = __VECS(rfc7539esp_tv_template) + .aead = { + ____VECS(rfc7539esp_tv_template), + .einval_allowed = 1, + .esp_aad = 1, + } } }, { .alg = "rmd128", diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 48da646651cb..d29983908c38 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -85,16 +85,22 @@ struct cipher_testvec { * @ctext: Pointer to the full authenticated ciphertext. For AEADs that * produce a separate "ciphertext" and "authentication tag", these * two parts are concatenated: ciphertext || tag. - * @novrfy: Decryption verification failure expected? + * @novrfy: If set, this is an inauthentic input test: only decryption is + * tested, and it is expected to fail with either -EBADMSG or + * @crypt_error if it is nonzero. * @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS? * (e.g. setkey() needs to fail due to a weak key) * @klen: Length of @key in bytes * @plen: Length of @ptext in bytes * @alen: Length of @assoc in bytes * @clen: Length of @ctext in bytes - * @setkey_error: Expected error from setkey() - * @setauthsize_error: Expected error from setauthsize() - * @crypt_error: Expected error from encrypt() and decrypt() + * @setkey_error: Expected error from setkey(). If set, neither encryption nor + * decryption is tested. + * @setauthsize_error: Expected error from setauthsize(). If set, neither + * encryption nor decryption is tested. + * @crypt_error: When @novrfy=0, the expected error from encrypt(). When + * @novrfy=1, an optional alternate error code that is acceptable + * for decrypt() to return besides -EBADMSG. */ struct aead_testvec { const char *key; -- cgit v1.2.3 From c441a909c68618ff64aa70394d0b270b0665a229 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 2 Dec 2019 13:42:29 -0800 Subject: crypto: compress - remove crt_u.compress (struct compress_tfm) crt_u.compress (struct compress_tfm) is pointless because its two fields, ->cot_compress() and ->cot_decompress(), always point to crypto_compress() and crypto_decompress(). Remove this pointless indirection, and just make crypto_comp_compress() and crypto_comp_decompress() be direct calls to what used to be crypto_compress() and crypto_decompress(). Also remove the unused function crypto_comp_cast(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- crypto/compress.c | 31 ++++++++++++------------------- crypto/internal.h | 1 - 3 files changed, 13 insertions(+), 21 deletions(-) (limited to 'crypto') diff --git a/crypto/api.c b/crypto/api.c index 4d3d13872fac..268129979bc2 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -301,7 +301,7 @@ static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask) return crypto_init_cipher_ops(tfm); case CRYPTO_ALG_TYPE_COMPRESS: - return crypto_init_compress_ops(tfm); + return 0; default: break; diff --git a/crypto/compress.c b/crypto/compress.c index e9edf8524787..9048fe390c46 100644 --- a/crypto/compress.c +++ b/crypto/compress.c @@ -6,34 +6,27 @@ * * Copyright (c) 2002 James Morris */ -#include #include -#include -#include #include "internal.h" -static int crypto_compress(struct crypto_tfm *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +int crypto_comp_compress(struct crypto_comp *comp, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) { + struct crypto_tfm *tfm = crypto_comp_tfm(comp); + return tfm->__crt_alg->cra_compress.coa_compress(tfm, src, slen, dst, dlen); } +EXPORT_SYMBOL_GPL(crypto_comp_compress); -static int crypto_decompress(struct crypto_tfm *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +int crypto_comp_decompress(struct crypto_comp *comp, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) { + struct crypto_tfm *tfm = crypto_comp_tfm(comp); + return tfm->__crt_alg->cra_compress.coa_decompress(tfm, src, slen, dst, dlen); } - -int crypto_init_compress_ops(struct crypto_tfm *tfm) -{ - struct compress_tfm *ops = &tfm->crt_compress; - - ops->cot_compress = crypto_compress; - ops->cot_decompress = crypto_decompress; - - return 0; -} +EXPORT_SYMBOL_GPL(crypto_comp_decompress); diff --git a/crypto/internal.h b/crypto/internal.h index 93df7bec844a..a58a2af4b669 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -59,7 +59,6 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); int crypto_init_cipher_ops(struct crypto_tfm *tfm); -int crypto_init_compress_ops(struct crypto_tfm *tfm); struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask); void crypto_larval_kill(struct crypto_alg *alg); -- cgit v1.2.3 From e8cfed5e4e2b5929371955f476a52a4c3398ead3 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 2 Dec 2019 13:42:30 -0800 Subject: crypto: cipher - remove crt_u.cipher (struct cipher_tfm) Of the three fields in crt_u.cipher (struct cipher_tfm), ->cit_setkey() is pointless because it always points to setkey() in crypto/cipher.c. ->cit_decrypt_one() and ->cit_encrypt_one() are slightly less pointless, since if the algorithm doesn't have an alignmask, they are set directly to ->cia_encrypt() and ->cia_decrypt(). However, this "optimization" isn't worthwhile because: - The "cipher" algorithm type is the only algorithm still using crt_u, so it's bloating every struct crypto_tfm for every algorithm type. - If the algorithm has an alignmask, this "optimization" actually makes things slower, as it causes 2 indirect calls per block rather than 1. - It adds extra code complexity. - Some templates already call ->cia_encrypt()/->cia_decrypt() directly instead of going through ->cit_encrypt_one()/->cit_decrypt_one(). - The "cipher" algorithm type never gives optimal performance anyway. For that, a higher-level type such as skcipher needs to be used. Therefore, just remove the extra indirection, and make crypto_cipher_setkey(), crypto_cipher_encrypt_one(), and crypto_cipher_decrypt_one() be direct calls into crypto/cipher.c. Also remove the unused function crypto_cipher_cast(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/api.c | 15 +-------- crypto/cipher.c | 92 ++++++++++++++++++++++--------------------------------- crypto/internal.h | 2 -- 3 files changed, 37 insertions(+), 72 deletions(-) (limited to 'crypto') diff --git a/crypto/api.c b/crypto/api.c index 268129979bc2..ef96142ceca7 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -295,20 +295,7 @@ static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask) if (type_obj) return type_obj->init(tfm, type, mask); - - switch (crypto_tfm_alg_type(tfm)) { - case CRYPTO_ALG_TYPE_CIPHER: - return crypto_init_cipher_ops(tfm); - - case CRYPTO_ALG_TYPE_COMPRESS: - return 0; - - default: - break; - } - - BUG(); - return -EINVAL; + return 0; } static void crypto_exit_ops(struct crypto_tfm *tfm) diff --git a/crypto/cipher.c b/crypto/cipher.c index 108427026e7c..aadd51cb7250 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -2,7 +2,7 @@ /* * Cryptographic API. * - * Cipher operations. + * Single-block cipher operations. * * Copyright (c) 2002 James Morris * Copyright (c) 2005 Herbert Xu @@ -16,11 +16,11 @@ #include #include "internal.h" -static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, +static int setkey_unaligned(struct crypto_cipher *tfm, const u8 *key, unsigned int keylen) { - struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); + struct cipher_alg *cia = crypto_cipher_alg(tfm); + unsigned long alignmask = crypto_cipher_alignmask(tfm); int ret; u8 *buffer, *alignbuffer; unsigned long absize; @@ -32,83 +32,63 @@ static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); - ret = cia->cia_setkey(tfm, alignbuffer, keylen); + ret = cia->cia_setkey(crypto_cipher_tfm(tfm), alignbuffer, keylen); memset(alignbuffer, 0, keylen); kfree(buffer); return ret; } -static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +int crypto_cipher_setkey(struct crypto_cipher *tfm, + const u8 *key, unsigned int keylen) { - struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); + struct cipher_alg *cia = crypto_cipher_alg(tfm); + unsigned long alignmask = crypto_cipher_alignmask(tfm); - tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; + crypto_cipher_clear_flags(tfm, CRYPTO_TFM_RES_MASK); if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { - tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + crypto_cipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } if ((unsigned long)key & alignmask) return setkey_unaligned(tfm, key, keylen); - return cia->cia_setkey(tfm, key, keylen); + return cia->cia_setkey(crypto_cipher_tfm(tfm), key, keylen); } +EXPORT_SYMBOL_GPL(crypto_cipher_setkey); -static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, - const u8 *), - struct crypto_tfm *tfm, - u8 *dst, const u8 *src) +static inline void cipher_crypt_one(struct crypto_cipher *tfm, + u8 *dst, const u8 *src, bool enc) { - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - unsigned int size = crypto_tfm_alg_blocksize(tfm); - u8 buffer[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK]; - u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); - - memcpy(tmp, src, size); - fn(tfm, tmp, tmp); - memcpy(dst, tmp, size); -} - -static void cipher_encrypt_unaligned(struct crypto_tfm *tfm, - u8 *dst, const u8 *src) -{ - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; + unsigned long alignmask = crypto_cipher_alignmask(tfm); + struct cipher_alg *cia = crypto_cipher_alg(tfm); + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = + enc ? cia->cia_encrypt : cia->cia_decrypt; if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { - cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src); - return; + unsigned int bs = crypto_cipher_blocksize(tfm); + u8 buffer[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK]; + u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); + + memcpy(tmp, src, bs); + fn(crypto_cipher_tfm(tfm), tmp, tmp); + memcpy(dst, tmp, bs); + } else { + fn(crypto_cipher_tfm(tfm), dst, src); } - - cipher->cia_encrypt(tfm, dst, src); } -static void cipher_decrypt_unaligned(struct crypto_tfm *tfm, - u8 *dst, const u8 *src) +void crypto_cipher_encrypt_one(struct crypto_cipher *tfm, + u8 *dst, const u8 *src) { - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - - if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { - cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src); - return; - } - - cipher->cia_decrypt(tfm, dst, src); + cipher_crypt_one(tfm, dst, src, true); } +EXPORT_SYMBOL_GPL(crypto_cipher_encrypt_one); -int crypto_init_cipher_ops(struct crypto_tfm *tfm) +void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, + u8 *dst, const u8 *src) { - struct cipher_tfm *ops = &tfm->crt_cipher; - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - - ops->cit_setkey = setkey; - ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ? - cipher_encrypt_unaligned : cipher->cia_encrypt; - ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ? - cipher_decrypt_unaligned : cipher->cia_decrypt; - - return 0; + cipher_crypt_one(tfm, dst, src, false); } +EXPORT_SYMBOL_GPL(crypto_cipher_decrypt_one); diff --git a/crypto/internal.h b/crypto/internal.h index a58a2af4b669..ff06a3bd1ca1 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -58,8 +58,6 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg) struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); -int crypto_init_cipher_ops(struct crypto_tfm *tfm); - struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask); void crypto_larval_kill(struct crypto_alg *alg); void crypto_alg_tested(const char *name, int err); -- cgit v1.2.3 From 91a71d612128f84f725022d7b7c5d5a741f6fdc7 Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Tue, 3 Dec 2019 14:31:12 -0500 Subject: padata: remove cpumask change notifier Since commit 63d3578892dc ("crypto: pcrypt - remove padata cpumask notifier") this feature is unused, so get rid of it. Signed-off-by: Daniel Jordan Cc: Eric Biggers Cc: Herbert Xu Cc: Jonathan Corbet Cc: Steffen Klassert Cc: linux-crypto@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/pcrypt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'crypto') diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index a4f3b3f342c8..d6696e217128 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 37f96694cf73ba116993a9d2d99ad6a75fa7fdb0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 5 Dec 2019 13:45:05 +0800 Subject: crypto: af_alg - Use bh_lock_sock in sk_destruct As af_alg_release_parent may be called from BH context (most notably due to an async request that only completes after socket closure, or as reported here because of an RCU-delayed sk_destruct call), we must use bh_lock_sock instead of lock_sock. Reported-by: syzbot+c2f1558d49e25cc36e5e@syzkaller.appspotmail.com Reported-by: Eric Dumazet Fixes: c840ac6af3f8 ("crypto: af_alg - Disallow bind/setkey/...") Cc: Signed-off-by: Herbert Xu --- crypto/af_alg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 0dceaabc6321..3d8e53010cda 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -134,11 +134,13 @@ void af_alg_release_parent(struct sock *sk) sk = ask->parent; ask = alg_sk(sk); - lock_sock(sk); + local_bh_disable(); + bh_lock_sock(sk); ask->nokey_refcnt -= nokey; if (!last) last = !--ask->refcnt; - release_sock(sk); + bh_unlock_sock(sk); + local_bh_enable(); if (last) sock_put(sk); -- cgit v1.2.3 From 7db3b61b6bba4310f454588c2ca6faf2958ad79f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 6 Dec 2019 13:55:17 +0800 Subject: crypto: api - Check spawn->alg under lock in crypto_drop_spawn We need to check whether spawn->alg is NULL under lock as otherwise the algorithm could be removed from under us after we have checked it and found it to be non-NULL. This could cause us to remove the spawn from a non-existent list. Fixes: 7ede5a5ba55a ("crypto: api - Fix crypto_drop_spawn crash...") Cc: Signed-off-by: Herbert Xu --- crypto/algapi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index b052f38edba6..9ecb4a57b342 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -669,11 +669,9 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn); void crypto_drop_spawn(struct crypto_spawn *spawn) { - if (!spawn->alg) - return; - down_write(&crypto_alg_sem); - list_del(&spawn->list); + if (spawn->alg) + list_del(&spawn->list); up_write(&crypto_alg_sem); } EXPORT_SYMBOL_GPL(crypto_drop_spawn); -- cgit v1.2.3 From 73669cc556462f4e50376538d77ee312142e8a8a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 7 Dec 2019 22:15:15 +0800 Subject: crypto: api - Fix race condition in crypto_spawn_alg The function crypto_spawn_alg is racy because it drops the lock before shooting the dying algorithm. The algorithm could disappear altogether before we shoot it. This patch fixes it by moving the shooting into the locked section. Fixes: 6bfd48096ff8 ("[CRYPTO] api: Added spawns") Signed-off-by: Herbert Xu --- crypto/algapi.c | 16 +++++----------- crypto/api.c | 3 +-- crypto/internal.h | 1 - 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index 9ecb4a57b342..54e844ad9364 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -679,22 +679,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn); static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn) { struct crypto_alg *alg; - struct crypto_alg *alg2; down_read(&crypto_alg_sem); alg = spawn->alg; - alg2 = alg; - if (alg2) - alg2 = crypto_mod_get(alg2); - up_read(&crypto_alg_sem); - - if (!alg2) { - if (alg) - crypto_shoot_alg(alg); - return ERR_PTR(-EAGAIN); + if (alg && !crypto_mod_get(alg)) { + alg->cra_flags |= CRYPTO_ALG_DYING; + alg = NULL; } + up_read(&crypto_alg_sem); - return alg; + return alg ?: ERR_PTR(-EAGAIN); } struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, diff --git a/crypto/api.c b/crypto/api.c index ef96142ceca7..676d54ffada8 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -331,13 +331,12 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) return len; } -void crypto_shoot_alg(struct crypto_alg *alg) +static void crypto_shoot_alg(struct crypto_alg *alg) { down_write(&crypto_alg_sem); alg->cra_flags |= CRYPTO_ALG_DYING; up_write(&crypto_alg_sem); } -EXPORT_SYMBOL_GPL(crypto_shoot_alg); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask) diff --git a/crypto/internal.h b/crypto/internal.h index ff06a3bd1ca1..d5ebc60c5143 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -65,7 +65,6 @@ void crypto_alg_tested(const char *name, int err); void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, struct crypto_alg *nalg); void crypto_remove_final(struct list_head *list); -void crypto_shoot_alg(struct crypto_alg *alg); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask); void *crypto_create_tfm(struct crypto_alg *alg, -- cgit v1.2.3 From 4f87ee118d16b4b2116a477229573ed5003b0d78 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 7 Dec 2019 22:15:17 +0800 Subject: crypto: api - Do not zap spawn->alg Currently when a spawn is removed we will zap its alg field. This is racy because the spawn could belong to an unregistered instance which may dereference the spawn->alg field. This patch fixes this by keeping spawn->alg constant and instead adding a new spawn->dead field to indicate that a spawn is going away. Signed-off-by: Herbert Xu --- crypto/algapi.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index 54e844ad9364..e858946adeed 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -93,15 +93,17 @@ static struct list_head *crypto_more_spawns(struct crypto_alg *alg, if (!spawn) return NULL; - n = list_next_entry(spawn, list); + n = list_prev_entry(spawn, list); + list_move(&spawn->list, secondary_spawns); - if (spawn->alg && &n->list != stack && !n->alg) - n->alg = (n->list.next == stack) ? alg : - &list_next_entry(n, list)->inst->alg; + if (list_is_last(&n->list, stack)) + return top; - list_move(&spawn->list, secondary_spawns); + n = list_next_entry(n, list); + if (!spawn->dead) + n->dead = false; - return &n->list == stack ? top : &n->inst->alg.cra_users; + return &n->inst->alg.cra_users; } static void crypto_remove_instance(struct crypto_instance *inst, @@ -160,7 +162,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, if (&inst->alg == nalg) break; - spawn->alg = NULL; + spawn->dead = true; spawns = &inst->alg.cra_users; /* @@ -179,7 +181,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, &secondary_spawns))); list_for_each_entry_safe(spawn, n, &secondary_spawns, list) { - if (spawn->alg) + if (!spawn->dead) list_move(&spawn->list, &spawn->alg->cra_users); else crypto_remove_instance(spawn->inst, list); @@ -670,7 +672,7 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn); void crypto_drop_spawn(struct crypto_spawn *spawn) { down_write(&crypto_alg_sem); - if (spawn->alg) + if (!spawn->dead) list_del(&spawn->list); up_write(&crypto_alg_sem); } @@ -682,7 +684,7 @@ static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn) down_read(&crypto_alg_sem); alg = spawn->alg; - if (alg && !crypto_mod_get(alg)) { + if (!spawn->dead && !crypto_mod_get(alg)) { alg->cra_flags |= CRYPTO_ALG_DYING; alg = NULL; } -- cgit v1.2.3 From 02244ba44bc366c38e188a3a90afc63dffae9897 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 7 Dec 2019 22:33:51 +0800 Subject: crypto: api - Add more comments to crypto_remove_spawns This patch explains the logic behind crypto_remove_spawns and its underling crypto_more_spawns. Signed-off-by: Herbert Xu --- crypto/algapi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index e858946adeed..cd643e294664 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -82,6 +82,15 @@ static void crypto_destroy_instance(struct crypto_alg *alg) crypto_tmpl_put(tmpl); } +/* + * This function adds a spawn to the list secondary_spawns which + * will be used at the end of crypto_remove_spawns to unregister + * instances, unless the spawn happens to be one that is depended + * on by the new algorithm (nalg in crypto_remove_spawns). + * + * This function is also responsible for resurrecting any algorithms + * in the dependency chain of nalg by unsetting n->dead. + */ static struct list_head *crypto_more_spawns(struct crypto_alg *alg, struct list_head *stack, struct list_head *top, @@ -128,6 +137,12 @@ static void crypto_remove_instance(struct crypto_instance *inst, BUG_ON(!list_empty(&inst->alg.cra_users)); } +/* + * Given an algorithm alg, remove all algorithms that depend on it + * through spawns. If nalg is not null, then exempt any algorithms + * that is depended on by nalg. This is useful when nalg itself + * depends on alg. + */ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, struct crypto_alg *nalg) { @@ -146,6 +161,11 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, list_move(&spawn->list, &top); } + /* + * Perform a depth-first walk starting from alg through + * the cra_users tree. The list stack records the path + * from alg to the current spawn. + */ spawns = ⊤ do { while (!list_empty(spawns)) { @@ -180,6 +200,11 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, } while ((spawns = crypto_more_spawns(alg, &stack, &top, &secondary_spawns))); + /* + * Remove all instances that are marked as dead. Also + * complete the resurrection of the others by moving them + * back to the cra_users list. + */ list_for_each_entry_safe(spawn, n, &secondary_spawns, list) { if (!spawn->dead) list_move(&spawn->list, &spawn->alg->cra_users); -- cgit v1.2.3 From fbce6be5aef5bad46f3af1650f7a62ec1b34318e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Dec 2019 13:42:51 +0800 Subject: crypto: shash - Add init_tfm/exit_tfm and verify descsize The shash interface supports a dynamic descsize field because of the presence of fallbacks (it's just padlock-sha actually, perhaps we can remove it one day). As it is the API does not verify the setting of descsize at all. It is up to the individual algorithms to ensure that descsize does not exceed the specified maximum value of HASH_MAX_DESCSIZE (going above would cause stack corruption). In order to allow the API to impose this limit directly, this patch adds init_tfm/exit_tfm hooks to the shash_alg structure. We can then verify the descsize setting in the API directly. Signed-off-by: Herbert Xu Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/shash.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'crypto') diff --git a/crypto/shash.c b/crypto/shash.c index 7989258a46b4..8042bb0df9c0 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -385,15 +385,41 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) return 0; } +static void crypto_shash_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_shash *hash = __crypto_shash_cast(tfm); + struct shash_alg *alg = crypto_shash_alg(hash); + + alg->exit_tfm(hash); +} + static int crypto_shash_init_tfm(struct crypto_tfm *tfm) { struct crypto_shash *hash = __crypto_shash_cast(tfm); struct shash_alg *alg = crypto_shash_alg(hash); + int err; hash->descsize = alg->descsize; shash_set_needkey(hash, alg); + if (alg->exit_tfm) + tfm->exit = crypto_shash_exit_tfm; + + if (!alg->init_tfm) + return 0; + + err = alg->init_tfm(hash); + if (err) + return err; + + /* ->init_tfm() may have increased the descsize. */ + if (WARN_ON_ONCE(hash->descsize > HASH_MAX_DESCSIZE)) { + if (alg->exit_tfm) + alg->exit_tfm(hash); + return -EINVAL; + } + return 0; } -- cgit v1.2.3 From d9e1670b8005999998b557c0e301bb68192bb1c8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Dec 2019 13:42:53 +0800 Subject: crypto: hmac - Use init_tfm/exit_tfm interface This patch switches hmac over to the new init_tfm/exit_tfm interface as opposed to cra_init/cra_exit. This way the shash API can make sure that descsize does not exceed the maximum. This patch also adds the API helper shash_alg_instance. Signed-off-by: Herbert Xu Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/hmac.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'crypto') diff --git a/crypto/hmac.c b/crypto/hmac.c index 377f07733e2f..685e49953605 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -138,12 +138,11 @@ static int hmac_finup(struct shash_desc *pdesc, const u8 *data, crypto_shash_finup(desc, out, ds, out); } -static int hmac_init_tfm(struct crypto_tfm *tfm) +static int hmac_init_tfm(struct crypto_shash *parent) { - struct crypto_shash *parent = __crypto_shash_cast(tfm); struct crypto_shash *hash; - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst); + struct shash_instance *inst = shash_alg_instance(parent); + struct crypto_shash_spawn *spawn = shash_instance_ctx(inst); struct hmac_ctx *ctx = hmac_ctx(parent); hash = crypto_spawn_shash(spawn); @@ -152,18 +151,14 @@ static int hmac_init_tfm(struct crypto_tfm *tfm) parent->descsize = sizeof(struct shash_desc) + crypto_shash_descsize(hash); - if (WARN_ON(parent->descsize > HASH_MAX_DESCSIZE)) { - crypto_free_shash(hash); - return -EINVAL; - } ctx->hash = hash; return 0; } -static void hmac_exit_tfm(struct crypto_tfm *tfm) +static void hmac_exit_tfm(struct crypto_shash *parent) { - struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm)); + struct hmac_ctx *ctx = hmac_ctx(parent); crypto_free_shash(ctx->hash); } @@ -217,9 +212,6 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) + ALIGN(ss * 2, crypto_tfm_ctx_alignment()); - inst->alg.base.cra_init = hmac_init_tfm; - inst->alg.base.cra_exit = hmac_exit_tfm; - inst->alg.init = hmac_init; inst->alg.update = hmac_update; inst->alg.final = hmac_final; @@ -227,6 +219,8 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.export = hmac_export; inst->alg.import = hmac_import; inst->alg.setkey = hmac_setkey; + inst->alg.init_tfm = hmac_init_tfm; + inst->alg.exit_tfm = hmac_exit_tfm; err = shash_register_instance(tmpl, inst); if (err) { -- cgit v1.2.3 From 2bbb3375d967155bccc86a5887d4a6e29c56b683 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 11 Dec 2019 10:50:11 +0800 Subject: crypto: api - fix unexpectedly getting generic implementation When CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y, the first lookup of an algorithm that needs to be instantiated using a template will always get the generic implementation, even when an accelerated one is available. This happens because the extra self-tests for the accelerated implementation allocate the generic implementation for comparison purposes, and then crypto_alg_tested() for the generic implementation "fulfills" the original request (i.e. sets crypto_larval::adult). This patch fixes this by only fulfilling the original request if we are currently the best outstanding larval as judged by the priority. If we're not the best then we will ask all waiters on that larval request to retry the lookup. Note that this patch introduces a behaviour change when the module providing the new algorithm is unregistered during the process. Previously we would have failed with ENOENT, after the patch we will instead redo the lookup. Fixes: 9a8a6b3f0950 ("crypto: testmgr - fuzz hashes against...") Fixes: d435e10e67be ("crypto: testmgr - fuzz skciphers against...") Fixes: 40153b10d91c ("crypto: testmgr - fuzz AEADs against...") Reported-by: Eric Biggers Signed-off-by: Herbert Xu Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/algapi.c | 24 +++++++++++++++++++++--- crypto/api.c | 4 +++- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index cd643e294664..9589b3f0041b 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -284,6 +284,7 @@ void crypto_alg_tested(const char *name, int err) struct crypto_alg *alg; struct crypto_alg *q; LIST_HEAD(list); + bool best; down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { @@ -307,6 +308,21 @@ found: alg->cra_flags |= CRYPTO_ALG_TESTED; + /* Only satisfy larval waiters if we are the best. */ + best = true; + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (crypto_is_moribund(q) || !crypto_is_larval(q)) + continue; + + if (strcmp(alg->cra_name, q->cra_name)) + continue; + + if (q->cra_priority > alg->cra_priority) { + best = false; + break; + } + } + list_for_each_entry(q, &crypto_alg_list, cra_list) { if (q == alg) continue; @@ -330,10 +346,12 @@ found: continue; if ((q->cra_flags ^ alg->cra_flags) & larval->mask) continue; - if (!crypto_mod_get(alg)) - continue; - larval->adult = alg; + if (best && crypto_mod_get(alg)) + larval->adult = alg; + else + larval->adult = ERR_PTR(-EAGAIN); + continue; } diff --git a/crypto/api.c b/crypto/api.c index 676d54ffada8..7d71a9b10e5f 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -97,7 +97,7 @@ static void crypto_larval_destroy(struct crypto_alg *alg) struct crypto_larval *larval = (void *)alg; BUG_ON(!crypto_is_larval(alg)); - if (larval->adult) + if (!IS_ERR_OR_NULL(larval->adult)) crypto_mod_put(larval->adult); kfree(larval); } @@ -178,6 +178,8 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) alg = ERR_PTR(-ETIMEDOUT); else if (!alg) alg = ERR_PTR(-ENOENT); + else if (IS_ERR(alg)) + ; else if (crypto_is_test_larval(larval) && !(alg->cra_flags & CRYPTO_ALG_TESTED)) alg = ERR_PTR(-EAGAIN); -- cgit v1.2.3 From c6d633a927499f35a06455a960ad6b5a59c87c2c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 15:51:19 -0800 Subject: crypto: algapi - make unregistration functions return void Some of the algorithm unregistration functions return -ENOENT when asked to unregister a non-registered algorithm, while others always return 0 or always return void. But no users check the return value, except for two of the bulk unregistration functions which print a message on error but still always return 0 to their caller, and crypto_del_alg() which calls crypto_unregister_instance() which always returns 0. Since unregistering a non-registered algorithm is always a kernel bug but there isn't anything callers should do to handle this situation at runtime, let's simplify things by making all the unregistration functions return void, and moving the error message into crypto_unregister_alg() and upgrading it to a WARN(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/acompress.c | 4 ++-- crypto/ahash.c | 4 ++-- crypto/algapi.c | 25 ++++++++----------------- crypto/crypto_user_base.c | 3 ++- crypto/scompress.c | 4 ++-- crypto/shash.c | 19 ++++++------------- 6 files changed, 22 insertions(+), 37 deletions(-) (limited to 'crypto') diff --git a/crypto/acompress.c b/crypto/acompress.c index abadcb035a41..84a76723e851 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -151,9 +151,9 @@ int crypto_register_acomp(struct acomp_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_acomp); -int crypto_unregister_acomp(struct acomp_alg *alg) +void crypto_unregister_acomp(struct acomp_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_acomp); diff --git a/crypto/ahash.c b/crypto/ahash.c index 3815b363a693..181bd851b429 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -598,9 +598,9 @@ int crypto_register_ahash(struct ahash_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_ahash); -int crypto_unregister_ahash(struct ahash_alg *alg) +void crypto_unregister_ahash(struct ahash_alg *alg) { - return crypto_unregister_alg(&alg->halg.base); + crypto_unregister_alg(&alg->halg.base); } EXPORT_SYMBOL_GPL(crypto_unregister_ahash); diff --git a/crypto/algapi.c b/crypto/algapi.c index 9589b3f0041b..fe57b4f696ac 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -442,7 +442,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) return 0; } -int crypto_unregister_alg(struct crypto_alg *alg) +void crypto_unregister_alg(struct crypto_alg *alg) { int ret; LIST_HEAD(list); @@ -451,15 +451,14 @@ int crypto_unregister_alg(struct crypto_alg *alg) ret = crypto_remove_alg(alg, &list); up_write(&crypto_alg_sem); - if (ret) - return ret; + if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name)) + return; BUG_ON(refcount_read(&alg->cra_refcnt) != 1); if (alg->cra_destroy) alg->cra_destroy(alg); crypto_remove_final(&list); - return 0; } EXPORT_SYMBOL_GPL(crypto_unregister_alg); @@ -483,18 +482,12 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_algs); -int crypto_unregister_algs(struct crypto_alg *algs, int count) +void crypto_unregister_algs(struct crypto_alg *algs, int count) { - int i, ret; - - for (i = 0; i < count; i++) { - ret = crypto_unregister_alg(&algs[i]); - if (ret) - pr_err("Failed to unregister %s %s: %d\n", - algs[i].cra_driver_name, algs[i].cra_name, ret); - } + int i; - return 0; + for (i = 0; i < count; i++) + crypto_unregister_alg(&algs[i]); } EXPORT_SYMBOL_GPL(crypto_unregister_algs); @@ -639,7 +632,7 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_instance); -int crypto_unregister_instance(struct crypto_instance *inst) +void crypto_unregister_instance(struct crypto_instance *inst) { LIST_HEAD(list); @@ -651,8 +644,6 @@ int crypto_unregister_instance(struct crypto_instance *inst) up_write(&crypto_alg_sem); crypto_remove_final(&list); - - return 0; } EXPORT_SYMBOL_GPL(crypto_unregister_instance); diff --git a/crypto/crypto_user_base.c b/crypto/crypto_user_base.c index b785c476de67..3fa20f12989f 100644 --- a/crypto/crypto_user_base.c +++ b/crypto/crypto_user_base.c @@ -323,7 +323,8 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, if (refcount_read(&alg->cra_refcnt) > 2) goto drop_alg; - err = crypto_unregister_instance((struct crypto_instance *)alg); + crypto_unregister_instance((struct crypto_instance *)alg); + err = 0; drop_alg: crypto_mod_put(alg); diff --git a/crypto/scompress.c b/crypto/scompress.c index 4d50750d01c6..738f4f8f0f41 100644 --- a/crypto/scompress.c +++ b/crypto/scompress.c @@ -266,9 +266,9 @@ int crypto_register_scomp(struct scomp_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_scomp); -int crypto_unregister_scomp(struct scomp_alg *alg) +void crypto_unregister_scomp(struct scomp_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_scomp); diff --git a/crypto/shash.c b/crypto/shash.c index 8042bb0df9c0..7243f60dab87 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -520,9 +520,9 @@ int crypto_register_shash(struct shash_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_shash); -int crypto_unregister_shash(struct shash_alg *alg) +void crypto_unregister_shash(struct shash_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_shash); @@ -546,19 +546,12 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_shashes); -int crypto_unregister_shashes(struct shash_alg *algs, int count) +void crypto_unregister_shashes(struct shash_alg *algs, int count) { - int i, ret; - - for (i = count - 1; i >= 0; --i) { - ret = crypto_unregister_shash(&algs[i]); - if (ret) - pr_err("Failed to unregister %s %s: %d\n", - algs[i].base.cra_driver_name, - algs[i].base.cra_name, ret); - } + int i; - return 0; + for (i = count - 1; i >= 0; --i) + crypto_unregister_shash(&algs[i]); } EXPORT_SYMBOL_GPL(crypto_unregister_shashes); -- cgit v1.2.3 From 5f567fffaae995dce3498e175e47d5a779fb0270 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 18 Dec 2019 15:53:01 +0800 Subject: crypto: api - Retain alg refcount in crypto_grab_spawn This patch changes crypto_grab_spawn to retain the reference count on the algorithm. This is because the caller needs to access the algorithm parameters and without the reference count the algorithm can be freed at any time. The reference count will be subsequently dropped by the crypto API once the instance has been registered. The helper crypto_drop_spawn will also conditionally drop the reference count depending on whether it has been registered. Note that the code is actually added to crypto_init_spawn. However, unless the caller activates this by setting spawn->dropref beforehand then nothing happens. The only caller that sets dropref is currently crypto_grab_spawn. Once all legacy users of crypto_init_spawn disappear, then we can kill the dropref flag. Internally each instance will maintain a list of its spawns prior to registration. This memory used by this list is shared with other fields that are only used after registration. In order for this to work a new flag spawn->registered is added to indicate whether spawn->inst can be used. Fixes: d6ef2f198d4c ("crypto: api - Add crypto_grab_spawn primitive") Signed-off-by: Herbert Xu --- crypto/algapi.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index fe57b4f696ac..363849983941 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -124,8 +124,6 @@ static void crypto_remove_instance(struct crypto_instance *inst, return; inst->alg.cra_flags |= CRYPTO_ALG_DEAD; - if (hlist_unhashed(&inst->list)) - return; if (!tmpl || !crypto_tmpl_get(tmpl)) return; @@ -175,17 +173,26 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, list); inst = spawn->inst; - BUG_ON(&inst->alg == alg); - list_move(&spawn->list, &stack); + spawn->dead = !spawn->registered || &inst->alg != nalg; + + if (!spawn->registered) + break; + + BUG_ON(&inst->alg == alg); if (&inst->alg == nalg) break; - spawn->dead = true; spawns = &inst->alg.cra_users; /* + * Even if spawn->registered is true, the + * instance itself may still be unregistered. + * This is because it may have failed during + * registration. Therefore we still need to + * make the following test. + * * We may encounter an unregistered instance here, since * an instance's spawns are set up prior to the instance * being registered. An unregistered instance will have @@ -208,7 +215,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, list_for_each_entry_safe(spawn, n, &secondary_spawns, list) { if (!spawn->dead) list_move(&spawn->list, &spawn->alg->cra_users); - else + else if (spawn->registered) crypto_remove_instance(spawn->inst, list); } } @@ -599,6 +606,7 @@ int crypto_register_instance(struct crypto_template *tmpl, struct crypto_instance *inst) { struct crypto_larval *larval; + struct crypto_spawn *spawn; int err; err = crypto_check_alg(&inst->alg); @@ -610,6 +618,23 @@ int crypto_register_instance(struct crypto_template *tmpl, down_write(&crypto_alg_sem); + larval = ERR_PTR(-EAGAIN); + for (spawn = inst->spawns; spawn;) { + struct crypto_spawn *next; + + if (spawn->dead) + goto unlock; + + next = spawn->next; + spawn->inst = inst; + spawn->registered = true; + + if (spawn->dropref) + crypto_mod_put(spawn->alg); + + spawn = next; + } + larval = __crypto_register_alg(&inst->alg); if (IS_ERR(larval)) goto unlock; @@ -655,7 +680,9 @@ int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, if (WARN_ON_ONCE(inst == NULL)) return -EINVAL; - spawn->inst = inst; + spawn->next = inst->spawns; + inst->spawns = spawn; + spawn->mask = mask; down_write(&crypto_alg_sem); @@ -697,8 +724,10 @@ int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name, if (IS_ERR(alg)) return PTR_ERR(alg); + spawn->dropref = true; err = crypto_init_spawn(spawn, alg, spawn->inst, mask); - crypto_mod_put(alg); + if (err) + crypto_mod_put(alg); return err; } EXPORT_SYMBOL_GPL(crypto_grab_spawn); @@ -709,6 +738,9 @@ void crypto_drop_spawn(struct crypto_spawn *spawn) if (!spawn->dead) list_del(&spawn->list); up_write(&crypto_alg_sem); + + if (spawn->dropref && !spawn->registered) + crypto_mod_put(spawn->alg); } EXPORT_SYMBOL_GPL(crypto_drop_spawn); -- cgit v1.2.3 From b3c16bfc6a79ae517ec3c44be615aed0ffa52c53 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 20 Dec 2019 13:29:40 +0800 Subject: crypto: skcipher - Add skcipher_ialg_simple helper This patch introduces the skcipher_ialg_simple helper which fetches the crypto_alg structure from a simple skcipher instance's spawn. This allows us to remove the third argument from the function skcipher_alloc_instance_simple. In doing so the reference count to the algorithm is now maintained by the Crypto API and the caller no longer needs to drop the alg refcount. Signed-off-by: Herbert Xu --- crypto/cbc.c | 15 +++++++-------- crypto/cfb.c | 5 +++-- crypto/ctr.c | 15 +++++++-------- crypto/ecb.c | 5 ++--- crypto/keywrap.c | 15 +++++++-------- crypto/ofb.c | 5 +++-- crypto/pcbc.c | 5 ++--- crypto/skcipher.c | 9 +++------ 8 files changed, 34 insertions(+), 40 deletions(-) (limited to 'crypto') diff --git a/crypto/cbc.c b/crypto/cbc.c index dd96bcf4d4b6..e6f6273a7d39 100644 --- a/crypto/cbc.c +++ b/crypto/cbc.c @@ -54,10 +54,12 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); + alg = skcipher_ialg_simple(inst); + err = -EINVAL; if (!is_power_of_2(alg->cra_blocksize)) goto out_free_inst; @@ -66,14 +68,11 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.decrypt = crypto_cbc_decrypt; err = skcipher_register_instance(tmpl, inst); - if (err) - goto out_free_inst; - goto out_put_alg; - + if (err) { out_free_inst: - inst->free(inst); -out_put_alg: - crypto_mod_put(alg); + inst->free(inst); + } + return err; } diff --git a/crypto/cfb.c b/crypto/cfb.c index 7b68fbb61732..4e5219bbcd19 100644 --- a/crypto/cfb.c +++ b/crypto/cfb.c @@ -203,10 +203,12 @@ static int crypto_cfb_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); + alg = skcipher_ialg_simple(inst); + /* CFB mode is a stream cipher. */ inst->alg.base.cra_blocksize = 1; @@ -223,7 +225,6 @@ static int crypto_cfb_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) inst->free(inst); - crypto_mod_put(alg); return err; } diff --git a/crypto/ctr.c b/crypto/ctr.c index 70a3fccb82f3..1e9d6b86b3c6 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -129,10 +129,12 @@ static int crypto_ctr_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); + alg = skcipher_ialg_simple(inst); + /* Block size must be >= 4 bytes. */ err = -EINVAL; if (alg->cra_blocksize < 4) @@ -155,14 +157,11 @@ static int crypto_ctr_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.decrypt = crypto_ctr_crypt; err = skcipher_register_instance(tmpl, inst); - if (err) - goto out_free_inst; - goto out_put_alg; - + if (err) { out_free_inst: - inst->free(inst); -out_put_alg: - crypto_mod_put(alg); + inst->free(inst); + } + return err; } diff --git a/crypto/ecb.c b/crypto/ecb.c index 9d6981ca7d5d..69a687cbdf21 100644 --- a/crypto/ecb.c +++ b/crypto/ecb.c @@ -61,10 +61,9 @@ static int crypto_ecb_decrypt(struct skcipher_request *req) static int crypto_ecb_create(struct crypto_template *tmpl, struct rtattr **tb) { struct skcipher_instance *inst; - struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); @@ -76,7 +75,7 @@ static int crypto_ecb_create(struct crypto_template *tmpl, struct rtattr **tb) err = skcipher_register_instance(tmpl, inst); if (err) inst->free(inst); - crypto_mod_put(alg); + return err; } diff --git a/crypto/keywrap.c b/crypto/keywrap.c index a155c88105ea..0355cce21b1e 100644 --- a/crypto/keywrap.c +++ b/crypto/keywrap.c @@ -266,10 +266,12 @@ static int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); + alg = skcipher_ialg_simple(inst); + err = -EINVAL; /* Section 5.1 requirement for KW */ if (alg->cra_blocksize != sizeof(struct crypto_kw_block)) @@ -283,14 +285,11 @@ static int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.decrypt = crypto_kw_decrypt; err = skcipher_register_instance(tmpl, inst); - if (err) - goto out_free_inst; - goto out_put_alg; - + if (err) { out_free_inst: - inst->free(inst); -out_put_alg: - crypto_mod_put(alg); + inst->free(inst); + } + return err; } diff --git a/crypto/ofb.c b/crypto/ofb.c index 133ff4c7f2c6..2ec68e3f2c55 100644 --- a/crypto/ofb.c +++ b/crypto/ofb.c @@ -55,10 +55,12 @@ static int crypto_ofb_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); + alg = skcipher_ialg_simple(inst); + /* OFB mode is a stream cipher. */ inst->alg.base.cra_blocksize = 1; @@ -75,7 +77,6 @@ static int crypto_ofb_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) inst->free(inst); - crypto_mod_put(alg); return err; } diff --git a/crypto/pcbc.c b/crypto/pcbc.c index 862cdb8d8b6c..ae921fb74dc9 100644 --- a/crypto/pcbc.c +++ b/crypto/pcbc.c @@ -153,10 +153,9 @@ static int crypto_pcbc_decrypt(struct skcipher_request *req) static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct skcipher_instance *inst; - struct crypto_alg *alg; int err; - inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + inst = skcipher_alloc_instance_simple(tmpl, tb); if (IS_ERR(inst)) return PTR_ERR(inst); @@ -166,7 +165,7 @@ static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb) err = skcipher_register_instance(tmpl, inst); if (err) inst->free(inst); - crypto_mod_put(alg); + return err; } diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 39a718d99220..37adb71f7759 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -938,15 +938,12 @@ static void skcipher_free_instance_simple(struct skcipher_instance *inst) * * @tmpl: the template being instantiated * @tb: the template parameters - * @cipher_alg_ret: on success, a pointer to the underlying cipher algorithm is - * returned here. It must be dropped with crypto_mod_put(). * * Return: a pointer to the new instance, or an ERR_PTR(). The caller still * needs to register the instance. */ -struct skcipher_instance * -skcipher_alloc_instance_simple(struct crypto_template *tmpl, struct rtattr **tb, - struct crypto_alg **cipher_alg_ret) +struct skcipher_instance *skcipher_alloc_instance_simple( + struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; struct crypto_alg *cipher_alg; @@ -982,6 +979,7 @@ skcipher_alloc_instance_simple(struct crypto_template *tmpl, struct rtattr **tb, if (err) goto err_free_inst; + spawn->dropref = true; err = crypto_init_spawn(spawn, cipher_alg, skcipher_crypto_instance(inst), CRYPTO_ALG_TYPE_MASK); @@ -1003,7 +1001,6 @@ skcipher_alloc_instance_simple(struct crypto_template *tmpl, struct rtattr **tb, inst->alg.init = skcipher_init_tfm_simple; inst->alg.exit = skcipher_exit_tfm_simple; - *cipher_alg_ret = cipher_alg; return inst; err_free_inst: -- cgit v1.2.3 From 70ffa8fd72b8df7ddfedc0b7db042eea75182fd5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 30 Dec 2019 13:41:15 -0600 Subject: crypto: skcipher - remove skcipher_walk_aead() skcipher_walk_aead() is unused and is identical to skcipher_walk_aead_encrypt(), so remove it. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 37adb71f7759..457e4ddc1482 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -549,15 +549,6 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk, return err; } -int skcipher_walk_aead(struct skcipher_walk *walk, struct aead_request *req, - bool atomic) -{ - walk->total = req->cryptlen; - - return skcipher_walk_aead_common(walk, req, atomic); -} -EXPORT_SYMBOL_GPL(skcipher_walk_aead); - int skcipher_walk_aead_encrypt(struct skcipher_walk *walk, struct aead_request *req, bool atomic) { -- cgit v1.2.3 From 674f368a952c48ede71784935a799a5205b92b6c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 30 Dec 2019 21:19:36 -0600 Subject: crypto: remove CRYPTO_TFM_RES_BAD_KEY_LEN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CRYPTO_TFM_RES_BAD_KEY_LEN flag was apparently meant as a way to make the ->setkey() functions provide more information about errors. However, no one actually checks for this flag, which makes it pointless. Also, many algorithms fail to set this flag when given a bad length key. Reviewing just the generic implementations, this is the case for aes-fixed-time, cbcmac, echainiv, nhpoly1305, pcrypt, rfc3686, rfc4309, rfc7539, rfc7539esp, salsa20, seqiv, and xcbc. But there are probably many more in arch/*/crypto/ and drivers/crypto/. Some algorithms can even set this flag when the key is the correct length. For example, authenc and authencesn set it when the key payload is malformed in any way (not just a bad length), the atmel-sha and ccree drivers can set it if a memory allocation fails, and the chelsio driver sets it for bad auth tag lengths, not just bad key lengths. So even if someone actually wanted to start checking this flag (which seems unlikely, since it's been unused for a long time), there would be a lot of work needed to get it working correctly. But it would probably be much better to go back to the drawing board and just define different return values, like -EINVAL if the key is invalid for the algorithm vs. -EKEYREJECTED if the key was rejected by a policy like "no weak keys". That would be much simpler, less error-prone, and easier to test. So just remove this flag. Signed-off-by: Eric Biggers Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- crypto/aegis128-core.c | 4 +--- crypto/aes_generic.c | 18 ++++++------------ crypto/anubis.c | 2 -- crypto/authenc.c | 6 +----- crypto/authencesn.c | 6 +----- crypto/blake2b_generic.c | 4 +--- crypto/blake2s_generic.c | 4 +--- crypto/camellia_generic.c | 5 +---- crypto/cast6_generic.c | 10 +++------- crypto/cipher.c | 4 +--- crypto/crc32_generic.c | 4 +--- crypto/crc32c_generic.c | 4 +--- crypto/essiv.c | 4 +--- crypto/ghash-generic.c | 4 +--- crypto/michael_mic.c | 4 +--- crypto/skcipher.c | 4 +--- crypto/sm4_generic.c | 16 +++++----------- crypto/twofish_common.c | 8 ++------ crypto/vmac.c | 4 +--- crypto/xxhash_generic.c | 4 +--- 20 files changed, 31 insertions(+), 88 deletions(-) (limited to 'crypto') diff --git a/crypto/aegis128-core.c b/crypto/aegis128-core.c index 71c11cb5bad1..44fb4956f0dd 100644 --- a/crypto/aegis128-core.c +++ b/crypto/aegis128-core.c @@ -372,10 +372,8 @@ static int crypto_aegis128_setkey(struct crypto_aead *aead, const u8 *key, { struct aegis_ctx *ctx = crypto_aead_ctx(aead); - if (keylen != AEGIS128_KEY_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen != AEGIS128_KEY_SIZE) return -EINVAL; - } memcpy(ctx->key.bytes, key, AEGIS128_KEY_SIZE); return 0; diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c index 22e5867177f1..27ab27931813 100644 --- a/crypto/aes_generic.c +++ b/crypto/aes_generic.c @@ -1127,24 +1127,18 @@ EXPORT_SYMBOL_GPL(crypto_it_tab); * @in_key: The input key. * @key_len: The size of the key. * - * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm - * is set. The function uses aes_expand_key() to expand the key. - * &crypto_aes_ctx _must_ be the private data embedded in @tfm which is - * retrieved with crypto_tfm_ctx(). + * This function uses aes_expand_key() to expand the key. &crypto_aes_ctx + * _must_ be the private data embedded in @tfm which is retrieved with + * crypto_tfm_ctx(). + * + * Return: 0 on success; -EINVAL on failure (only happens for bad key lengths) */ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - int ret; - - ret = aes_expandkey(ctx, in_key, key_len); - if (!ret) - return 0; - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; + return aes_expandkey(ctx, in_key, key_len); } EXPORT_SYMBOL_GPL(crypto_aes_set_key); diff --git a/crypto/anubis.c b/crypto/anubis.c index f9ce78fde6ee..5da0241ef453 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -464,7 +464,6 @@ static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key, { struct anubis_ctx *ctx = crypto_tfm_ctx(tfm); const __be32 *key = (const __be32 *)in_key; - u32 *flags = &tfm->crt_flags; int N, R, i, r; u32 kappa[ANUBIS_MAX_N]; u32 inter[ANUBIS_MAX_N]; @@ -474,7 +473,6 @@ static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key, case 32: case 36: case 40: break; default: - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } diff --git a/crypto/authenc.c b/crypto/authenc.c index 3f0ed9402582..0da80632e872 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -91,7 +91,7 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, int err = -EINVAL; if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) - goto badkey; + goto out; crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) & @@ -113,10 +113,6 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, out: memzero_explicit(&keys, sizeof(keys)); return err; - -badkey: - crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); - goto out; } static void authenc_geniv_ahash_done(struct crypto_async_request *areq, int err) diff --git a/crypto/authencesn.c b/crypto/authencesn.c index adb7554fca29..749527e1b617 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -65,7 +65,7 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 * int err = -EINVAL; if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) - goto badkey; + goto out; crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) & @@ -87,10 +87,6 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 * out: memzero_explicit(&keys, sizeof(keys)); return err; - -badkey: - crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN); - goto out; } static int crypto_authenc_esn_genicv_tail(struct aead_request *req, diff --git a/crypto/blake2b_generic.c b/crypto/blake2b_generic.c index d04b1788dc42..1d262374fa4e 100644 --- a/crypto/blake2b_generic.c +++ b/crypto/blake2b_generic.c @@ -147,10 +147,8 @@ static int blake2b_setkey(struct crypto_shash *tfm, const u8 *key, { struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(tfm); - if (keylen == 0 || keylen > BLAKE2B_KEYBYTES) { - crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen == 0 || keylen > BLAKE2B_KEYBYTES) return -EINVAL; - } memcpy(tctx->key, key, keylen); tctx->keylen = keylen; diff --git a/crypto/blake2s_generic.c b/crypto/blake2s_generic.c index ed0c74640470..005783ff45ad 100644 --- a/crypto/blake2s_generic.c +++ b/crypto/blake2s_generic.c @@ -17,10 +17,8 @@ static int crypto_blake2s_setkey(struct crypto_shash *tfm, const u8 *key, { struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm); - if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE) { - crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE) return -EINVAL; - } memcpy(tctx->key, key, keylen); tctx->keylen = keylen; diff --git a/crypto/camellia_generic.c b/crypto/camellia_generic.c index b6a1121e2478..9a5783e5196a 100644 --- a/crypto/camellia_generic.c +++ b/crypto/camellia_generic.c @@ -970,12 +970,9 @@ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key, { struct camellia_ctx *cctx = crypto_tfm_ctx(tfm); const unsigned char *key = (const unsigned char *)in_key; - u32 *flags = &tfm->crt_flags; - if (key_len != 16 && key_len != 24 && key_len != 32) { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + if (key_len != 16 && key_len != 24 && key_len != 32) return -EINVAL; - } cctx->key_length = key_len; diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c index 85328522c5ca..c77ff6c8a2b2 100644 --- a/crypto/cast6_generic.c +++ b/crypto/cast6_generic.c @@ -103,17 +103,14 @@ static inline void W(u32 *key, unsigned int i) key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]); } -int __cast6_setkey(struct cast6_ctx *c, const u8 *in_key, - unsigned key_len, u32 *flags) +int __cast6_setkey(struct cast6_ctx *c, const u8 *in_key, unsigned int key_len) { int i; u32 key[8]; __be32 p_key[8]; /* padded key */ - if (key_len % 4 != 0) { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + if (key_len % 4 != 0) return -EINVAL; - } memset(p_key, 0, 32); memcpy(p_key, in_key, key_len); @@ -148,8 +145,7 @@ EXPORT_SYMBOL_GPL(__cast6_setkey); int cast6_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { - return __cast6_setkey(crypto_tfm_ctx(tfm), key, keylen, - &tfm->crt_flags); + return __cast6_setkey(crypto_tfm_ctx(tfm), key, keylen); } EXPORT_SYMBOL_GPL(cast6_setkey); diff --git a/crypto/cipher.c b/crypto/cipher.c index aadd51cb7250..0fb7042a709d 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -46,10 +46,8 @@ int crypto_cipher_setkey(struct crypto_cipher *tfm, unsigned long alignmask = crypto_cipher_alignmask(tfm); crypto_cipher_clear_flags(tfm, CRYPTO_TFM_RES_MASK); - if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { - crypto_cipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) return -EINVAL; - } if ((unsigned long)key & alignmask) return setkey_unaligned(tfm, key, keylen); diff --git a/crypto/crc32_generic.c b/crypto/crc32_generic.c index 9e97912280bd..0e103fb5dd77 100644 --- a/crypto/crc32_generic.c +++ b/crypto/crc32_generic.c @@ -60,10 +60,8 @@ static int crc32_setkey(struct crypto_shash *hash, const u8 *key, { u32 *mctx = crypto_shash_ctx(hash); - if (keylen != sizeof(u32)) { - crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen != sizeof(u32)) return -EINVAL; - } *mctx = get_unaligned_le32(key); return 0; } diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c index 7b25fe82072c..7fa9b0788685 100644 --- a/crypto/crc32c_generic.c +++ b/crypto/crc32c_generic.c @@ -74,10 +74,8 @@ static int chksum_setkey(struct crypto_shash *tfm, const u8 *key, { struct chksum_ctx *mctx = crypto_shash_ctx(tfm); - if (keylen != sizeof(mctx->key)) { - crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen != sizeof(mctx->key)) return -EINVAL; - } mctx->key = get_unaligned_le32(key); return 0; } diff --git a/crypto/essiv.c b/crypto/essiv.c index e4b32c2ea7ec..f49bd6fc6972 100644 --- a/crypto/essiv.c +++ b/crypto/essiv.c @@ -117,10 +117,8 @@ static int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, if (err) return err; - if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) { - crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) return -EINVAL; - } desc->tfm = tctx->hash; err = crypto_shash_init(desc) ?: diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c index 5027b3461c92..c70d163c1ac9 100644 --- a/crypto/ghash-generic.c +++ b/crypto/ghash-generic.c @@ -58,10 +58,8 @@ static int ghash_setkey(struct crypto_shash *tfm, 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); + if (keylen != GHASH_BLOCK_SIZE) return -EINVAL; - } if (ctx->gf128) gf128mul_free_4k(ctx->gf128); diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index 20e6220f46f6..63350c4ad461 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -137,10 +137,8 @@ static int michael_setkey(struct crypto_shash *tfm, const u8 *key, const __le32 *data = (const __le32 *)key; - if (keylen != 8) { - crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen != 8) return -EINVAL; - } mctx->l = le32_to_cpu(data[0]); mctx->r = le32_to_cpu(data[1]); diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 457e4ddc1482..8c8735f75478 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -603,10 +603,8 @@ int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned long alignmask = crypto_skcipher_alignmask(tfm); int err; - if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { - crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) return -EINVAL; - } if ((unsigned long)key & alignmask) err = skcipher_setkey_unaligned(tfm, key, keylen); diff --git a/crypto/sm4_generic.c b/crypto/sm4_generic.c index 71ffb343709a..016dbc595705 100644 --- a/crypto/sm4_generic.c +++ b/crypto/sm4_generic.c @@ -143,29 +143,23 @@ int crypto_sm4_expand_key(struct crypto_sm4_ctx *ctx, const u8 *in_key, EXPORT_SYMBOL_GPL(crypto_sm4_expand_key); /** - * crypto_sm4_set_key - Set the AES key. + * crypto_sm4_set_key - Set the SM4 key. * @tfm: The %crypto_tfm that is used in the context. * @in_key: The input key. * @key_len: The size of the key. * - * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm - * is set. The function uses crypto_sm4_expand_key() to expand the key. + * This function uses crypto_sm4_expand_key() to expand the key. * &crypto_sm4_ctx _must_ be the private data embedded in @tfm which is * retrieved with crypto_tfm_ctx(). + * + * Return: 0 on success; -EINVAL on failure (only happens for bad key lengths) */ int crypto_sm4_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - int ret; - - ret = crypto_sm4_expand_key(ctx, in_key, key_len); - if (!ret) - return 0; - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; + return crypto_sm4_expand_key(ctx, in_key, key_len); } EXPORT_SYMBOL_GPL(crypto_sm4_set_key); diff --git a/crypto/twofish_common.c b/crypto/twofish_common.c index 222fc765c57a..d23fa531b91f 100644 --- a/crypto/twofish_common.c +++ b/crypto/twofish_common.c @@ -567,7 +567,7 @@ static const u8 calc_sb_tbl[512] = { /* Perform the key setup. */ int __twofish_setkey(struct twofish_ctx *ctx, const u8 *key, - unsigned int key_len, u32 *flags) + unsigned int key_len) { int i, j, k; @@ -584,10 +584,7 @@ int __twofish_setkey(struct twofish_ctx *ctx, const u8 *key, /* Check key length. */ if (key_len % 8) - { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; /* unsupported key length */ - } /* Compute the first two words of the S vector. The magic numbers are * the entries of the RS matrix, preprocessed through poly_to_exp. The @@ -688,8 +685,7 @@ EXPORT_SYMBOL_GPL(__twofish_setkey); int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) { - return __twofish_setkey(crypto_tfm_ctx(tfm), key, key_len, - &tfm->crt_flags); + return __twofish_setkey(crypto_tfm_ctx(tfm), key, key_len); } EXPORT_SYMBOL_GPL(twofish_setkey); diff --git a/crypto/vmac.c b/crypto/vmac.c index f50a85060b39..0bbb34dc87c4 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -435,10 +435,8 @@ static int vmac_setkey(struct crypto_shash *tfm, unsigned int i; int err; - if (keylen != VMAC_KEY_LEN) { - crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + if (keylen != VMAC_KEY_LEN) return -EINVAL; - } err = crypto_cipher_setkey(tctx->cipher, key, keylen); if (err) diff --git a/crypto/xxhash_generic.c b/crypto/xxhash_generic.c index 4aad2c0f40a9..55d1c8a76127 100644 --- a/crypto/xxhash_generic.c +++ b/crypto/xxhash_generic.c @@ -22,10 +22,8 @@ static int xxhash64_setkey(struct crypto_shash *tfm, const u8 *key, { 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); + if (keylen != sizeof(tctx->seed)) return -EINVAL; - } tctx->seed = get_unaligned_le64(key); return 0; } -- cgit v1.2.3 From c4c4db0d59774f6ab726edd012711490437345c2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 30 Dec 2019 21:19:37 -0600 Subject: crypto: remove CRYPTO_TFM_RES_WEAK_KEY The CRYPTO_TFM_RES_WEAK_KEY flag was apparently meant as a way to make the ->setkey() functions provide more information about errors. However, no one actually checks for this flag, which makes it pointless. There are also no tests that verify that all algorithms actually set (or don't set) it correctly. This is also the last remaining CRYPTO_TFM_RES_* flag, which means that it's the only thing still needing all the boilerplate code which propagates these flags around from child => parent tfms. And if someone ever needs to distinguish this error in the future (which is somewhat unlikely, as it's been unneeded for a long time), it would be much better to just define a new return value like -EKEYREJECTED. That would be much simpler, less error-prone, and easier to test. So just remove this flag. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/des_generic.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'crypto') diff --git a/crypto/des_generic.c b/crypto/des_generic.c index 6e13a4a29ecb..c85354a5e94c 100644 --- a/crypto/des_generic.c +++ b/crypto/des_generic.c @@ -29,11 +29,8 @@ static int des_setkey(struct crypto_tfm *tfm, const u8 *key, else err = 0; } - - if (err) { + if (err) memset(dctx, 0, sizeof(*dctx)); - crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - } return err; } @@ -64,11 +61,8 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, else err = 0; } - - if (err) { + if (err) memset(dctx, 0, sizeof(*dctx)); - crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - } return err; } -- cgit v1.2.3 From af5034e8e4a5838fc77e476c1a91822e449d5869 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 30 Dec 2019 21:19:38 -0600 Subject: crypto: remove propagation of CRYPTO_TFM_RES_* flags The CRYPTO_TFM_RES_* flags were apparently meant as a way to make the ->setkey() functions provide more information about errors. But these flags weren't actually being used or tested, and in many cases they weren't being set correctly anyway. So they've now been removed. Also, if someone ever actually needs to start better distinguishing ->setkey() errors (which is somewhat unlikely, as this has been unneeded for a long time), we'd be much better off just defining different return values, like -EINVAL if the key is invalid for the algorithm vs. -EKEYREJECTED if the key was rejected by a policy like "no weak keys". That would be much simpler, less error-prone, and easier to test. So just remove CRYPTO_TFM_RES_MASK and all the unneeded logic that propagates these flags around. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/adiantum.c | 8 -------- crypto/authenc.c | 6 ------ crypto/authencesn.c | 6 ------ crypto/ccm.c | 20 ++++---------------- crypto/chacha20poly1305.c | 7 +------ crypto/cipher.c | 1 - crypto/cryptd.c | 13 ++----------- crypto/ctr.c | 7 +------ crypto/cts.c | 6 +----- crypto/essiv.c | 22 ++++------------------ crypto/gcm.c | 19 ++----------------- crypto/lrw.c | 2 -- crypto/simd.c | 12 ++---------- crypto/skcipher.c | 6 +----- crypto/xts.c | 8 +------- 15 files changed, 19 insertions(+), 124 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index aded26092268..30cffb45b88f 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -135,9 +135,6 @@ static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(tctx->streamcipher, key, keylen); - crypto_skcipher_set_flags(tfm, - crypto_skcipher_get_flags(tctx->streamcipher) & - CRYPTO_TFM_RES_MASK); if (err) return err; @@ -167,9 +164,6 @@ static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key, CRYPTO_TFM_REQ_MASK); err = crypto_cipher_setkey(tctx->blockcipher, keyp, BLOCKCIPHER_KEY_SIZE); - crypto_skcipher_set_flags(tfm, - crypto_cipher_get_flags(tctx->blockcipher) & - CRYPTO_TFM_RES_MASK); if (err) goto out; keyp += BLOCKCIPHER_KEY_SIZE; @@ -182,8 +176,6 @@ static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key, crypto_shash_set_flags(tctx->hash, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); err = crypto_shash_setkey(tctx->hash, keyp, NHPOLY1305_KEY_SIZE); - crypto_skcipher_set_flags(tfm, crypto_shash_get_flags(tctx->hash) & - CRYPTO_TFM_RES_MASK); keyp += NHPOLY1305_KEY_SIZE; WARN_ON(keyp != &data->derived_keys[ARRAY_SIZE(data->derived_keys)]); out: diff --git a/crypto/authenc.c b/crypto/authenc.c index 0da80632e872..15aaddd34171 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -97,9 +97,6 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) & CRYPTO_TFM_REQ_MASK); err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen); - crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) & - CRYPTO_TFM_RES_MASK); - if (err) goto out; @@ -107,9 +104,6 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, crypto_skcipher_set_flags(enc, crypto_aead_get_flags(authenc) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(enc, keys.enckey, keys.enckeylen); - crypto_aead_set_flags(authenc, crypto_skcipher_get_flags(enc) & - CRYPTO_TFM_RES_MASK); - out: memzero_explicit(&keys, sizeof(keys)); return err; diff --git a/crypto/authencesn.c b/crypto/authencesn.c index 749527e1b617..fc81324ce881 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -71,9 +71,6 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 * crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) & CRYPTO_TFM_REQ_MASK); err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen); - crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) & - CRYPTO_TFM_RES_MASK); - if (err) goto out; @@ -81,9 +78,6 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 * crypto_skcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(enc, keys.enckey, keys.enckeylen); - crypto_aead_set_flags(authenc_esn, crypto_skcipher_get_flags(enc) & - CRYPTO_TFM_RES_MASK); - out: memzero_explicit(&keys, sizeof(keys)); return err; diff --git a/crypto/ccm.c b/crypto/ccm.c index 380eb619f657..44104524e95a 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -91,26 +91,19 @@ static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key, struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); struct crypto_skcipher *ctr = ctx->ctr; struct crypto_ahash *mac = ctx->mac; - int err = 0; + int err; crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(ctr, key, keylen); - crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) & - CRYPTO_TFM_RES_MASK); if (err) - goto out; + return err; crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK); crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); - err = crypto_ahash_setkey(mac, key, keylen); - crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) & - CRYPTO_TFM_RES_MASK); - -out: - return err; + return crypto_ahash_setkey(mac, key, keylen); } static int crypto_ccm_setauthsize(struct crypto_aead *tfm, @@ -604,7 +597,6 @@ static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key, { struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent); struct crypto_aead *child = ctx->child; - int err; if (keylen < 3) return -EINVAL; @@ -615,11 +607,7 @@ static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key, crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_aead_setkey(child, key, keylen); - crypto_aead_set_flags(parent, crypto_aead_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_aead_setkey(child, key, keylen); } static int crypto_rfc4309_setauthsize(struct crypto_aead *parent, diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index 74e824e537e6..88cbdaba43b8 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -477,7 +477,6 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct chachapoly_ctx *ctx = crypto_aead_ctx(aead); - int err; if (keylen != ctx->saltlen + CHACHA_KEY_SIZE) return -EINVAL; @@ -488,11 +487,7 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, crypto_skcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); - - err = crypto_skcipher_setkey(ctx->chacha, key, keylen); - crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctx->chacha) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_skcipher_setkey(ctx->chacha, key, keylen); } static int chachapoly_setauthsize(struct crypto_aead *tfm, diff --git a/crypto/cipher.c b/crypto/cipher.c index 0fb7042a709d..fd78150deb1c 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -45,7 +45,6 @@ int crypto_cipher_setkey(struct crypto_cipher *tfm, struct cipher_alg *cia = crypto_cipher_alg(tfm); unsigned long alignmask = crypto_cipher_alignmask(tfm); - crypto_cipher_clear_flags(tfm, CRYPTO_TFM_RES_MASK); if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) return -EINVAL; diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 2c6649b10923..cd94243a1605 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -252,17 +252,12 @@ static int cryptd_skcipher_setkey(struct crypto_skcipher *parent, { struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent); struct crypto_sync_skcipher *child = ctx->child; - int err; crypto_sync_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_sync_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_sync_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, - crypto_sync_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_sync_skcipher_setkey(child, key, keylen); } static void cryptd_skcipher_complete(struct skcipher_request *req, int err) @@ -491,15 +486,11 @@ static int cryptd_hash_setkey(struct crypto_ahash *parent, { struct cryptd_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; + return crypto_shash_setkey(child, key, keylen); } static int cryptd_hash_enqueue(struct ahash_request *req, diff --git a/crypto/ctr.c b/crypto/ctr.c index 1e9d6b86b3c6..b63b19de68a9 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -170,7 +170,6 @@ static int crypto_rfc3686_setkey(struct crypto_skcipher *parent, { struct crypto_rfc3686_ctx *ctx = crypto_skcipher_ctx(parent); struct crypto_skcipher *child = ctx->child; - int err; /* the nonce is stored in bytes at end of key */ if (keylen < CTR_RFC3686_NONCE_SIZE) @@ -184,11 +183,7 @@ static int crypto_rfc3686_setkey(struct crypto_skcipher *parent, crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_skcipher_setkey(child, key, keylen); } static int crypto_rfc3686_crypt(struct skcipher_request *req) diff --git a/crypto/cts.c b/crypto/cts.c index 6b6087dbb62a..a0bb994f8b11 100644 --- a/crypto/cts.c +++ b/crypto/cts.c @@ -78,15 +78,11 @@ static int crypto_cts_setkey(struct crypto_skcipher *parent, const u8 *key, { struct crypto_cts_ctx *ctx = crypto_skcipher_ctx(parent); struct crypto_skcipher *child = ctx->child; - int err; crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_skcipher_setkey(child, key, keylen); } static void cts_cbc_crypt_done(struct crypto_async_request *areq, int err) diff --git a/crypto/essiv.c b/crypto/essiv.c index f49bd6fc6972..61d9000ae4ad 100644 --- a/crypto/essiv.c +++ b/crypto/essiv.c @@ -75,9 +75,6 @@ static int essiv_skcipher_setkey(struct crypto_skcipher *tfm, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(tctx->u.skcipher, key, keylen); - crypto_skcipher_set_flags(tfm, - crypto_skcipher_get_flags(tctx->u.skcipher) & - CRYPTO_TFM_RES_MASK); if (err) return err; @@ -90,13 +87,8 @@ static int essiv_skcipher_setkey(struct crypto_skcipher *tfm, crypto_cipher_set_flags(tctx->essiv_cipher, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(tctx->essiv_cipher, salt, - crypto_shash_digestsize(tctx->hash)); - crypto_skcipher_set_flags(tfm, - crypto_cipher_get_flags(tctx->essiv_cipher) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_cipher_setkey(tctx->essiv_cipher, salt, + crypto_shash_digestsize(tctx->hash)); } static int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, @@ -112,8 +104,6 @@ static int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, crypto_aead_set_flags(tctx->u.aead, crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); err = crypto_aead_setkey(tctx->u.aead, key, keylen); - crypto_aead_set_flags(tfm, crypto_aead_get_flags(tctx->u.aead) & - CRYPTO_TFM_RES_MASK); if (err) return err; @@ -130,12 +120,8 @@ static int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK); crypto_cipher_set_flags(tctx->essiv_cipher, crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(tctx->essiv_cipher, salt, - crypto_shash_digestsize(tctx->hash)); - crypto_aead_set_flags(tfm, crypto_cipher_get_flags(tctx->essiv_cipher) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_cipher_setkey(tctx->essiv_cipher, salt, + crypto_shash_digestsize(tctx->hash)); } static int essiv_aead_setauthsize(struct crypto_aead *tfm, diff --git a/crypto/gcm.c b/crypto/gcm.c index 73884208f075..7041cb1b6fd5 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -111,8 +111,6 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(ctr, key, keylen); - crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) & - CRYPTO_TFM_RES_MASK); if (err) return err; @@ -141,9 +139,6 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, crypto_ahash_set_flags(ghash, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_ahash_setkey(ghash, (u8 *)&data->hash, sizeof(be128)); - crypto_aead_set_flags(aead, crypto_ahash_get_flags(ghash) & - CRYPTO_TFM_RES_MASK); - out: kzfree(data); return err; @@ -727,7 +722,6 @@ static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key, { struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent); struct crypto_aead *child = ctx->child; - int err; if (keylen < 4) return -EINVAL; @@ -738,11 +732,7 @@ static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key, crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_aead_setkey(child, key, keylen); - crypto_aead_set_flags(parent, crypto_aead_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_aead_setkey(child, key, keylen); } static int crypto_rfc4106_setauthsize(struct crypto_aead *parent, @@ -956,7 +946,6 @@ static int crypto_rfc4543_setkey(struct crypto_aead *parent, const u8 *key, { struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent); struct crypto_aead *child = ctx->child; - int err; if (keylen < 4) return -EINVAL; @@ -967,11 +956,7 @@ static int crypto_rfc4543_setkey(struct crypto_aead *parent, const u8 *key, crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_aead_setkey(child, key, keylen); - crypto_aead_set_flags(parent, crypto_aead_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_aead_setkey(child, key, keylen); } static int crypto_rfc4543_setauthsize(struct crypto_aead *parent, diff --git a/crypto/lrw.c b/crypto/lrw.c index be829f6afc8e..8ebd79276c78 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -79,8 +79,6 @@ static int setkey(struct crypto_skcipher *parent, const u8 *key, crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(child, key, keylen - bsize); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); if (err) return err; diff --git a/crypto/simd.c b/crypto/simd.c index 48876266cf2d..56885af49c24 100644 --- a/crypto/simd.c +++ b/crypto/simd.c @@ -52,15 +52,11 @@ static int simd_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, { struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); struct crypto_skcipher *child = &ctx->cryptd_tfm->base; - int err; crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, key_len); - crypto_skcipher_set_flags(tfm, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_skcipher_setkey(child, key, key_len); } static int simd_skcipher_encrypt(struct skcipher_request *req) @@ -295,15 +291,11 @@ static int simd_aead_setkey(struct crypto_aead *tfm, const u8 *key, { struct simd_aead_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_aead *child = &ctx->cryptd_tfm->base; - int err; crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); - err = crypto_aead_setkey(child, key, key_len); - crypto_aead_set_flags(tfm, crypto_aead_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_aead_setkey(child, key, key_len); } static int simd_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 8c8735f75478..89137a197fc8 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -876,15 +876,11 @@ static int skcipher_setkey_simple(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); - int err; crypto_cipher_clear_flags(cipher, CRYPTO_TFM_REQ_MASK); crypto_cipher_set_flags(cipher, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(cipher, key, keylen); - crypto_skcipher_set_flags(tfm, crypto_cipher_get_flags(cipher) & - CRYPTO_TFM_RES_MASK); - return err; + return crypto_cipher_setkey(cipher, key, keylen); } static int skcipher_init_tfm_simple(struct crypto_skcipher *tfm) diff --git a/crypto/xts.c b/crypto/xts.c index ab117633d64e..19d55489e78b 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -61,8 +61,6 @@ static int setkey(struct crypto_skcipher *parent, const u8 *key, crypto_cipher_set_flags(tweak, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); err = crypto_cipher_setkey(tweak, key + keylen, keylen); - crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(tweak) & - CRYPTO_TFM_RES_MASK); if (err) return err; @@ -71,11 +69,7 @@ static int setkey(struct crypto_skcipher *parent, const u8 *key, crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_skcipher_setkey(child, key, keylen); } /* -- cgit v1.2.3 From ff67062796e97cbb009ab0ca30176abb24b9a325 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:41 -0800 Subject: crypto: algapi - make crypto_drop_spawn() a no-op on uninitialized spawns Make crypto_drop_spawn() do nothing when the spawn hasn't been initialized with an algorithm yet. This will allow simplifying error handling in all the template ->create() functions, since on error they will be able to just call their usual "free instance" function, rather than having to handle dropping just the spawns that have been initialized so far. This does assume the spawn starts out zero-filled, but that's always the case since instances are allocated with kzalloc(). And some other code already assumes this anyway. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/algapi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index 363849983941..4c761f48110d 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -734,6 +734,9 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn); void crypto_drop_spawn(struct crypto_spawn *spawn) { + if (!spawn->alg) /* not yet initialized? */ + return; + down_write(&crypto_alg_sem); if (!spawn->dead) list_del(&spawn->list); -- cgit v1.2.3 From ca94e9374a7d86e0594ed824b437656ca83d47b4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:42 -0800 Subject: crypto: algapi - make crypto_grab_spawn() handle an ERR_PTR() name To allow further simplifying template ->create() functions, make crypto_grab_spawn() handle an ERR_PTR() name by passing back the error. For most templates, this will allow the result of crypto_attr_alg_name() to be passed directly to crypto_grab_*(), rather than first having to assign it to a variable [where it can then potentially be misused, as it was in the rfc7539 template prior to commit 5e27f38f1f3f ("crypto: chacha20poly1305 - set cra_name correctly")] and check it for error. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/algapi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index 4c761f48110d..a5223c5f2275 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -720,6 +720,10 @@ int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name, struct crypto_alg *alg; int err; + /* Allow the result of crypto_attr_alg_name() to be passed directly */ + if (IS_ERR(name)) + return PTR_ERR(name); + alg = crypto_find_alg(name, spawn->frontend, type, mask); if (IS_ERR(alg)) return PTR_ERR(alg); -- cgit v1.2.3 From b9f76dddb1f9f70e008b982381bbc9a67c9b8c66 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:45 -0800 Subject: crypto: skcipher - pass instance to crypto_grab_skcipher() Initializing a crypto_skcipher_spawn currently requires: 1. Set spawn->base.inst to point to the instance. 2. Call crypto_grab_skcipher(). But there's no reason for these steps to be separate, and in fact this unneeded complication has caused at least one bug, the one fixed by commit 6db43410179b ("crypto: adiantum - initialize crypto_spawn::inst") So just make crypto_grab_skcipher() take the instance as an argument. To keep the function calls from getting too unwieldy due to this extra argument, also introduce a 'mask' variable into the affected places which weren't already using one. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/adiantum.c | 11 ++++++----- crypto/authenc.c | 12 ++++++------ crypto/authencesn.c | 12 ++++++------ crypto/ccm.c | 9 +++++---- crypto/chacha20poly1305.c | 13 ++++++------- crypto/cryptd.c | 4 ++-- crypto/ctr.c | 4 ++-- crypto/cts.c | 9 +++++---- crypto/essiv.c | 13 +++++-------- crypto/gcm.c | 13 ++++++------- crypto/lrw.c | 15 ++++++++------- crypto/skcipher.c | 4 +++- crypto/xts.c | 9 +++++---- 13 files changed, 65 insertions(+), 63 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 30cffb45b88f..567071464fab 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -493,6 +493,7 @@ static bool adiantum_supported_algorithms(struct skcipher_alg *streamcipher_alg, static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; const char *streamcipher_name; const char *blockcipher_name; const char *nhpoly1305_name; @@ -511,6 +512,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + streamcipher_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(streamcipher_name)) return PTR_ERR(streamcipher_name); @@ -531,11 +534,9 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) ictx = skcipher_instance_ctx(inst); /* Stream cipher, e.g. "xchacha12" */ - crypto_set_skcipher_spawn(&ictx->streamcipher_spawn, - skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(&ictx->streamcipher_spawn, streamcipher_name, - 0, crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ictx->streamcipher_spawn, + skcipher_crypto_instance(inst), + streamcipher_name, 0, mask); if (err) goto out_free_inst; streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn); diff --git a/crypto/authenc.c b/crypto/authenc.c index 15aaddd34171..e31bcec58564 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -373,6 +373,7 @@ static int crypto_authenc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct hash_alg_common *auth; struct crypto_alg *auth_base; @@ -388,9 +389,10 @@ static int crypto_authenc_create(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | - crypto_requires_sync(algt->type, algt->mask)); + CRYPTO_ALG_TYPE_AHASH_MASK | mask); if (IS_ERR(auth)) return PTR_ERR(auth); @@ -413,10 +415,8 @@ static int crypto_authenc_create(struct crypto_template *tmpl, if (err) goto err_free_inst; - crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst)); - err = crypto_grab_skcipher(&ctx->enc, enc_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), + enc_name, 0, mask); if (err) goto err_drop_auth; diff --git a/crypto/authencesn.c b/crypto/authencesn.c index fc81324ce881..83bda7f905bb 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -391,6 +391,7 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct hash_alg_common *auth; struct crypto_alg *auth_base; @@ -406,9 +407,10 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | - crypto_requires_sync(algt->type, algt->mask)); + CRYPTO_ALG_TYPE_AHASH_MASK | mask); if (IS_ERR(auth)) return PTR_ERR(auth); @@ -431,10 +433,8 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, if (err) goto err_free_inst; - crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst)); - err = crypto_grab_skcipher(&ctx->enc, enc_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), + enc_name, 0, mask); if (err) goto err_drop_auth; diff --git a/crypto/ccm.c b/crypto/ccm.c index 44104524e95a..4414f0ddfe5a 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -450,6 +450,7 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, const char *mac_name) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct skcipher_alg *ctr; struct crypto_alg *mac_alg; @@ -464,6 +465,8 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + mac_alg = crypto_find_alg(mac_name, &crypto_ahash_type, CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_AHASH_MASK | @@ -488,10 +491,8 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, if (err) goto err_free_inst; - crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst)); - err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst), + ctr_name, 0, mask); if (err) goto err_drop_mac; diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index 88cbdaba43b8..09d5a34ab339 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -558,6 +558,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, const char *name, unsigned int ivsize) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct skcipher_alg *chacha; struct crypto_alg *poly; @@ -576,6 +577,8 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + chacha_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(chacha_name)) return PTR_ERR(chacha_name); @@ -585,9 +588,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, poly = crypto_find_alg(poly_name, &crypto_ahash_type, CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | - crypto_requires_sync(algt->type, - algt->mask)); + CRYPTO_ALG_TYPE_AHASH_MASK | mask); if (IS_ERR(poly)) return PTR_ERR(poly); poly_hash = __crypto_hash_alg_common(poly); @@ -608,10 +609,8 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, if (err) goto err_free_inst; - crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst)); - err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ctx->chacha, aead_crypto_instance(inst), + chacha_name, 0, mask); if (err) goto err_drop_poly; diff --git a/crypto/cryptd.c b/crypto/cryptd.c index cd94243a1605..a0fe10624cfd 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -416,8 +416,8 @@ static int cryptd_create_skcipher(struct crypto_template *tmpl, ctx = skcipher_instance_ctx(inst); ctx->queue = queue; - crypto_set_skcipher_spawn(&ctx->spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(&ctx->spawn, name, type, mask); + err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst), + name, type, mask); if (err) goto out_free_inst; diff --git a/crypto/ctr.c b/crypto/ctr.c index b63b19de68a9..a8feab621c6c 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -286,8 +286,8 @@ static int crypto_rfc3686_create(struct crypto_template *tmpl, spawn = skcipher_instance_ctx(inst); - crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(spawn, cipher_name, 0, mask); + err = crypto_grab_skcipher(spawn, skcipher_crypto_instance(inst), + cipher_name, 0, mask); if (err) goto err_free_inst; diff --git a/crypto/cts.c b/crypto/cts.c index a0bb994f8b11..48188adc8e91 100644 --- a/crypto/cts.c +++ b/crypto/cts.c @@ -328,6 +328,7 @@ static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb) struct crypto_attr_type *algt; struct skcipher_alg *alg; const char *cipher_name; + u32 mask; int err; algt = crypto_get_attr_type(tb); @@ -337,6 +338,8 @@ static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb) if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + cipher_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(cipher_name)) return PTR_ERR(cipher_name); @@ -347,10 +350,8 @@ static int crypto_cts_create(struct crypto_template *tmpl, struct rtattr **tb) spawn = skcipher_instance_ctx(inst); - crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(spawn, cipher_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(spawn, skcipher_crypto_instance(inst), + cipher_name, 0, mask); if (err) goto err_free_inst; diff --git a/crypto/essiv.c b/crypto/essiv.c index 61d9000ae4ad..0e45f5b4f67f 100644 --- a/crypto/essiv.c +++ b/crypto/essiv.c @@ -452,6 +452,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) struct shash_alg *hash_alg; int ivsize; u32 type; + u32 mask; int err; algt = crypto_get_attr_type(tb); @@ -467,6 +468,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) return PTR_ERR(shash_name); type = algt->type & algt->mask; + mask = crypto_requires_sync(algt->type, algt->mask); switch (type) { case CRYPTO_ALG_TYPE_SKCIPHER: @@ -479,11 +481,8 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) ictx = crypto_instance_ctx(inst); /* Symmetric cipher, e.g., "cbc(aes)" */ - crypto_set_skcipher_spawn(&ictx->u.skcipher_spawn, inst); - err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, - inner_cipher_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, inst, + inner_cipher_name, 0, mask); if (err) goto out_free_inst; skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn); @@ -503,9 +502,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) /* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */ crypto_set_aead_spawn(&ictx->u.aead_spawn, inst); err = crypto_grab_aead(&ictx->u.aead_spawn, - inner_cipher_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + inner_cipher_name, 0, mask); if (err) goto out_free_inst; aead_alg = crypto_spawn_aead_alg(&ictx->u.aead_spawn); diff --git a/crypto/gcm.c b/crypto/gcm.c index 7041cb1b6fd5..887f472734b6 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -580,6 +580,7 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, const char *ghash_name) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct skcipher_alg *ctr; struct crypto_alg *ghash_alg; @@ -594,11 +595,11 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type, CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | - crypto_requires_sync(algt->type, - algt->mask)); + CRYPTO_ALG_TYPE_AHASH_MASK | mask); if (IS_ERR(ghash_alg)) return PTR_ERR(ghash_alg); @@ -620,10 +621,8 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, ghash->digestsize != 16) goto err_drop_ghash; - crypto_set_skcipher_spawn(&ctx->ctr, aead_crypto_instance(inst)); - err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(&ctx->ctr, aead_crypto_instance(inst), + ctr_name, 0, mask); if (err) goto err_drop_ghash; diff --git a/crypto/lrw.c b/crypto/lrw.c index 8ebd79276c78..63c485c0d8a6 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -301,6 +301,7 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) struct skcipher_alg *alg; const char *cipher_name; char ecb_name[CRYPTO_MAX_ALG_NAME]; + u32 mask; int err; algt = crypto_get_attr_type(tb); @@ -310,6 +311,8 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + cipher_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(cipher_name)) return PTR_ERR(cipher_name); @@ -320,19 +323,17 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) spawn = skcipher_instance_ctx(inst); - crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(spawn, cipher_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(spawn, skcipher_crypto_instance(inst), + cipher_name, 0, mask); if (err == -ENOENT) { err = -ENAMETOOLONG; if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)", cipher_name) >= CRYPTO_MAX_ALG_NAME) goto err_free_inst; - err = crypto_grab_skcipher(spawn, ecb_name, 0, - crypto_requires_sync(algt->type, - algt->mask)); + err = crypto_grab_skcipher(spawn, + skcipher_crypto_instance(inst), + ecb_name, 0, mask); } if (err) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 89137a197fc8..8759d473a154 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -747,8 +747,10 @@ static const struct crypto_type crypto_skcipher_type = { }; int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, - const char *name, u32 type, u32 mask) + struct crypto_instance *inst, + const char *name, u32 type, u32 mask) { + spawn->base.inst = inst; spawn->base.frontend = &crypto_skcipher_type; return crypto_grab_spawn(&spawn->base, name, type, mask); } diff --git a/crypto/xts.c b/crypto/xts.c index 19d55489e78b..29efa15f1495 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -355,20 +355,21 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) ctx = skcipher_instance_ctx(inst); - crypto_set_skcipher_spawn(&ctx->spawn, skcipher_crypto_instance(inst)); - mask = crypto_requires_off(algt->type, algt->mask, CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC); - err = crypto_grab_skcipher(&ctx->spawn, cipher_name, 0, mask); + err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst), + cipher_name, 0, mask); if (err == -ENOENT) { err = -ENAMETOOLONG; if (snprintf(ctx->name, CRYPTO_MAX_ALG_NAME, "ecb(%s)", cipher_name) >= CRYPTO_MAX_ALG_NAME) goto err_free_inst; - err = crypto_grab_skcipher(&ctx->spawn, ctx->name, 0, mask); + err = crypto_grab_skcipher(&ctx->spawn, + skcipher_crypto_instance(inst), + ctx->name, 0, mask); } if (err) -- cgit v1.2.3 From cd900f0cacd7601dabdd028e8cbdbf2a7041cee2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:46 -0800 Subject: crypto: aead - pass instance to crypto_grab_aead() Initializing a crypto_aead_spawn currently requires: 1. Set spawn->base.inst to point to the instance. 2. Call crypto_grab_aead(). But there's no reason for these steps to be separate, and in fact this unneeded complication has caused at least one bug, the one fixed by commit 6db43410179b ("crypto: adiantum - initialize crypto_spawn::inst") So just make crypto_grab_aead() take the instance as an argument. To keep the function calls from getting too unwieldy due to this extra argument, also introduce a 'mask' variable into the affected places which weren't already using one. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/aead.c | 6 ++++-- crypto/ccm.c | 8 +++++--- crypto/cryptd.c | 4 ++-- crypto/essiv.c | 3 +-- crypto/gcm.c | 16 ++++++++++------ crypto/geniv.c | 4 ++-- crypto/pcrypt.c | 5 ++--- 7 files changed, 26 insertions(+), 20 deletions(-) (limited to 'crypto') diff --git a/crypto/aead.c b/crypto/aead.c index 47f16d139e8e..c7135e00b8ea 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -207,9 +207,11 @@ static const struct crypto_type crypto_aead_type = { .tfmsize = offsetof(struct crypto_aead, base), }; -int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, - u32 type, u32 mask) +int crypto_grab_aead(struct crypto_aead_spawn *spawn, + struct crypto_instance *inst, + const char *name, u32 type, u32 mask) { + spawn->base.inst = inst; spawn->base.frontend = &crypto_aead_type; return crypto_grab_spawn(&spawn->base, name, type, mask); } diff --git a/crypto/ccm.c b/crypto/ccm.c index 4414f0ddfe5a..48766e81b933 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -734,6 +734,7 @@ static int crypto_rfc4309_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct crypto_aead_spawn *spawn; struct aead_alg *alg; @@ -747,6 +748,8 @@ static int crypto_rfc4309_create(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + ccm_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(ccm_name)) return PTR_ERR(ccm_name); @@ -756,9 +759,8 @@ static int crypto_rfc4309_create(struct crypto_template *tmpl, return -ENOMEM; spawn = aead_instance_ctx(inst); - crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); - err = crypto_grab_aead(spawn, ccm_name, 0, - crypto_requires_sync(algt->type, algt->mask)); + err = crypto_grab_aead(spawn, aead_crypto_instance(inst), + ccm_name, 0, mask); if (err) goto out_free_inst; diff --git a/crypto/cryptd.c b/crypto/cryptd.c index a0fe10624cfd..a03ac2878017 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -865,8 +865,8 @@ static int cryptd_create_aead(struct crypto_template *tmpl, ctx = aead_instance_ctx(inst); ctx->queue = queue; - crypto_set_aead_spawn(&ctx->aead_spawn, aead_crypto_instance(inst)); - err = crypto_grab_aead(&ctx->aead_spawn, name, type, mask); + err = crypto_grab_aead(&ctx->aead_spawn, aead_crypto_instance(inst), + name, type, mask); if (err) goto out_free_inst; diff --git a/crypto/essiv.c b/crypto/essiv.c index 0e45f5b4f67f..20d7c1fdbf5d 100644 --- a/crypto/essiv.c +++ b/crypto/essiv.c @@ -500,8 +500,7 @@ static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) ictx = crypto_instance_ctx(inst); /* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */ - crypto_set_aead_spawn(&ictx->u.aead_spawn, inst); - err = crypto_grab_aead(&ictx->u.aead_spawn, + err = crypto_grab_aead(&ictx->u.aead_spawn, inst, inner_cipher_name, 0, mask); if (err) goto out_free_inst; diff --git a/crypto/gcm.c b/crypto/gcm.c index 887f472734b6..72649b8cbf2a 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -856,6 +856,7 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct crypto_aead_spawn *spawn; struct aead_alg *alg; @@ -869,6 +870,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + ccm_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(ccm_name)) return PTR_ERR(ccm_name); @@ -878,9 +881,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, return -ENOMEM; spawn = aead_instance_ctx(inst); - crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); - err = crypto_grab_aead(spawn, ccm_name, 0, - crypto_requires_sync(algt->type, algt->mask)); + err = crypto_grab_aead(spawn, aead_crypto_instance(inst), + ccm_name, 0, mask); if (err) goto out_free_inst; @@ -1087,6 +1089,7 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; + u32 mask; struct aead_instance *inst; struct crypto_aead_spawn *spawn; struct aead_alg *alg; @@ -1101,6 +1104,8 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + ccm_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(ccm_name)) return PTR_ERR(ccm_name); @@ -1111,9 +1116,8 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, ctx = aead_instance_ctx(inst); spawn = &ctx->aead; - crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); - err = crypto_grab_aead(spawn, ccm_name, 0, - crypto_requires_sync(algt->type, algt->mask)); + err = crypto_grab_aead(spawn, aead_crypto_instance(inst), + ccm_name, 0, mask); if (err) goto out_free_inst; diff --git a/crypto/geniv.c b/crypto/geniv.c index b9e45a2a98b5..7afa48414f3a 100644 --- a/crypto/geniv.c +++ b/crypto/geniv.c @@ -64,8 +64,8 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, /* Ignore async algorithms if necessary. */ mask |= crypto_requires_sync(algt->type, algt->mask); - crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); - err = crypto_grab_aead(spawn, name, type, mask); + err = crypto_grab_aead(spawn, aead_crypto_instance(inst), + name, type, mask); if (err) goto err_free_inst; diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index d6696e217128..1b632139a8c1 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -258,9 +258,8 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb, if (!ctx->psdec) goto out_free_psenc; - crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst)); - - err = crypto_grab_aead(&ctx->spawn, name, 0, 0); + err = crypto_grab_aead(&ctx->spawn, aead_crypto_instance(inst), + name, 0, 0); if (err) goto out_free_psdec; -- cgit v1.2.3 From 73bed26f73a120f14cabf8d214ec5078bb42dea9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:47 -0800 Subject: crypto: akcipher - pass instance to crypto_grab_akcipher() Initializing a crypto_akcipher_spawn currently requires: 1. Set spawn->base.inst to point to the instance. 2. Call crypto_grab_akcipher(). But there's no reason for these steps to be separate, and in fact this unneeded complication has caused at least one bug, the one fixed by commit 6db43410179b ("crypto: adiantum - initialize crypto_spawn::inst") So just make crypto_grab_akcipher() take the instance as an argument. To keep the function call from getting too unwieldy due to this extra argument, also introduce a 'mask' variable into pkcs1pad_create(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/akcipher.c | 6 ++++-- crypto/rsa-pkcs1pad.c | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/akcipher.c b/crypto/akcipher.c index 7d5cf4939423..84ccf9b02bbe 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -90,9 +90,11 @@ static const struct crypto_type crypto_akcipher_type = { .tfmsize = offsetof(struct crypto_akcipher, base), }; -int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn, const char *name, - u32 type, u32 mask) +int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn, + struct crypto_instance *inst, + const char *name, u32 type, u32 mask) { + spawn->base.inst = inst; spawn->base.frontend = &crypto_akcipher_type; return crypto_grab_spawn(&spawn->base, name, type, mask); } diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c index 0aa489711ec4..176b63afec8d 100644 --- a/crypto/rsa-pkcs1pad.c +++ b/crypto/rsa-pkcs1pad.c @@ -598,6 +598,7 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb) { const struct rsa_asn1_template *digest_info; struct crypto_attr_type *algt; + u32 mask; struct akcipher_instance *inst; struct pkcs1pad_inst_ctx *ctx; struct crypto_akcipher_spawn *spawn; @@ -613,6 +614,8 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb) if ((algt->type ^ CRYPTO_ALG_TYPE_AKCIPHER) & algt->mask) return -EINVAL; + mask = crypto_requires_sync(algt->type, algt->mask); + rsa_alg_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(rsa_alg_name)) return PTR_ERR(rsa_alg_name); @@ -636,9 +639,8 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb) spawn = &ctx->spawn; ctx->digest_info = digest_info; - crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst)); - err = crypto_grab_akcipher(spawn, rsa_alg_name, 0, - crypto_requires_sync(algt->type, algt->mask)); + err = crypto_grab_akcipher(spawn, akcipher_crypto_instance(inst), + rsa_alg_name, 0, mask); if (err) goto out_free_inst; -- cgit v1.2.3 From de95c9574108ec304083ed574304ab3b60b4167c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:48 -0800 Subject: crypto: algapi - pass instance to crypto_grab_spawn() Currently, crypto_spawn::inst is first used temporarily to pass the instance to crypto_grab_spawn(). Then crypto_init_spawn() overwrites it with crypto_spawn::next, which shares the same union. Finally, crypto_spawn::inst is set again when the instance is registered. Make this less convoluted by just passing the instance as an argument to crypto_grab_spawn() instead. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/adiantum.c | 6 +++--- crypto/aead.c | 3 +-- crypto/akcipher.c | 3 +-- crypto/algapi.c | 6 +++--- crypto/skcipher.c | 3 +-- 5 files changed, 9 insertions(+), 12 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 567071464fab..76a41881ee8c 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -542,9 +542,9 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn); /* Block cipher, e.g. "aes" */ - crypto_set_spawn(&ictx->blockcipher_spawn, - skcipher_crypto_instance(inst)); - err = crypto_grab_spawn(&ictx->blockcipher_spawn, blockcipher_name, + err = crypto_grab_spawn(&ictx->blockcipher_spawn, + skcipher_crypto_instance(inst), + blockcipher_name, CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK); if (err) goto out_drop_streamcipher; diff --git a/crypto/aead.c b/crypto/aead.c index c7135e00b8ea..02a0db076d7e 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -211,9 +211,8 @@ int crypto_grab_aead(struct crypto_aead_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask) { - spawn->base.inst = inst; spawn->base.frontend = &crypto_aead_type; - return crypto_grab_spawn(&spawn->base, name, type, mask); + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); } EXPORT_SYMBOL_GPL(crypto_grab_aead); diff --git a/crypto/akcipher.c b/crypto/akcipher.c index 84ccf9b02bbe..eeed6c151d2f 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -94,9 +94,8 @@ int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask) { - spawn->base.inst = inst; spawn->base.frontend = &crypto_akcipher_type; - return crypto_grab_spawn(&spawn->base, name, type, mask); + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); } EXPORT_SYMBOL_GPL(crypto_grab_akcipher); diff --git a/crypto/algapi.c b/crypto/algapi.c index a5223c5f2275..a25ce02918f8 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -714,8 +714,8 @@ out: } EXPORT_SYMBOL_GPL(crypto_init_spawn2); -int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name, - u32 type, u32 mask) +int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, + const char *name, u32 type, u32 mask) { struct crypto_alg *alg; int err; @@ -729,7 +729,7 @@ int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name, return PTR_ERR(alg); spawn->dropref = true; - err = crypto_init_spawn(spawn, alg, spawn->inst, mask); + err = crypto_init_spawn(spawn, alg, inst, mask); if (err) crypto_mod_put(alg); return err; diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 8759d473a154..15c033c960f7 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -750,9 +750,8 @@ int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask) { - spawn->base.inst = inst; spawn->base.frontend = &crypto_skcipher_type; - return crypto_grab_spawn(&spawn->base, name, type, mask); + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); } EXPORT_SYMBOL_GPL(crypto_grab_skcipher); -- cgit v1.2.3 From fdfad1fffc2aa199fb447c152a00a5e383a5b973 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:49 -0800 Subject: crypto: shash - introduce crypto_grab_shash() Currently, shash spawns are initialized by using shash_attr_alg() or crypto_alg_mod_lookup() to look up the shash algorithm, then calling crypto_init_shash_spawn(). This is different from how skcipher, aead, and akcipher spawns are initialized (they use crypto_grab_*()), and for no good reason. This difference introduces unnecessary complexity. The crypto_grab_*() functions used to have some problems, like not holding a reference to the algorithm and requiring the caller to initialize spawn->base.inst. But those problems are fixed now. So, let's introduce crypto_grab_shash() so that we can convert all templates to the same way of initializing their spawns. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/shash.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'crypto') diff --git a/crypto/shash.c b/crypto/shash.c index 7243f60dab87..e0872ac2729a 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -469,6 +469,15 @@ static const struct crypto_type crypto_shash_type = { .tfmsize = offsetof(struct crypto_shash, base), }; +int crypto_grab_shash(struct crypto_shash_spawn *spawn, + struct crypto_instance *inst, + const char *name, u32 type, u32 mask) +{ + spawn->base.frontend = &crypto_shash_type; + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_grab_shash); + struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type, u32 mask) { -- cgit v1.2.3 From 84a9c938e5063709f799fd6bab17a8ea723c2eb5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:50 -0800 Subject: crypto: ahash - introduce crypto_grab_ahash() Currently, ahash spawns are initialized by using ahash_attr_alg() or crypto_find_alg() to look up the ahash algorithm, then calling crypto_init_ahash_spawn(). This is different from how skcipher, aead, and akcipher spawns are initialized (they use crypto_grab_*()), and for no good reason. This difference introduces unnecessary complexity. The crypto_grab_*() functions used to have some problems, like not holding a reference to the algorithm and requiring the caller to initialize spawn->base.inst. But those problems are fixed now. So, let's introduce crypto_grab_ahash() so that we can convert all templates to the same way of initializing their spawns. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ahash.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index 181bd851b429..e98a1398ed7f 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -556,6 +556,15 @@ const struct crypto_type crypto_ahash_type = { }; EXPORT_SYMBOL_GPL(crypto_ahash_type); +int crypto_grab_ahash(struct crypto_ahash_spawn *spawn, + struct crypto_instance *inst, + const char *name, u32 type, u32 mask) +{ + spawn->base.frontend = &crypto_ahash_type; + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_grab_ahash); + struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask) { -- cgit v1.2.3 From ba44840747bdd60095881830af0d75f0e5017c99 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:52 -0800 Subject: crypto: adiantum - use crypto_grab_{cipher,shash} and simplify error paths Make the adiantum template use the new functions crypto_grab_cipher() and crypto_grab_shash() to initialize its cipher and shash spawns. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/adiantum.c | 85 ++++++++++++++++--------------------------------------- 1 file changed, 25 insertions(+), 60 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 76a41881ee8c..5b8aa14ccb55 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -39,8 +39,6 @@ #include #include -#include "internal.h" - /* * Size of right-hand part of input data, in bytes; also the size of the block * cipher's block size and the hash function's output. @@ -64,7 +62,7 @@ struct adiantum_instance_ctx { struct crypto_skcipher_spawn streamcipher_spawn; - struct crypto_spawn blockcipher_spawn; + struct crypto_cipher_spawn blockcipher_spawn; struct crypto_shash_spawn hash_spawn; }; @@ -410,7 +408,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm) if (IS_ERR(streamcipher)) return PTR_ERR(streamcipher); - blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn); + blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn.base); if (IS_ERR(blockcipher)) { err = PTR_ERR(blockcipher); goto err_free_streamcipher; @@ -461,7 +459,7 @@ static void adiantum_free_instance(struct skcipher_instance *inst) struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst); crypto_drop_skcipher(&ictx->streamcipher_spawn); - crypto_drop_spawn(&ictx->blockcipher_spawn); + crypto_drop_cipher(&ictx->blockcipher_spawn); crypto_drop_shash(&ictx->hash_spawn); kfree(inst); } @@ -494,14 +492,11 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; u32 mask; - const char *streamcipher_name; - const char *blockcipher_name; const char *nhpoly1305_name; struct skcipher_instance *inst; struct adiantum_instance_ctx *ictx; struct skcipher_alg *streamcipher_alg; struct crypto_alg *blockcipher_alg; - struct crypto_alg *_hash_alg; struct shash_alg *hash_alg; int err; @@ -514,20 +509,6 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) mask = crypto_requires_sync(algt->type, algt->mask); - streamcipher_name = crypto_attr_alg_name(tb[1]); - if (IS_ERR(streamcipher_name)) - return PTR_ERR(streamcipher_name); - - blockcipher_name = crypto_attr_alg_name(tb[2]); - if (IS_ERR(blockcipher_name)) - return PTR_ERR(blockcipher_name); - - nhpoly1305_name = crypto_attr_alg_name(tb[3]); - if (nhpoly1305_name == ERR_PTR(-ENOENT)) - nhpoly1305_name = "nhpoly1305"; - if (IS_ERR(nhpoly1305_name)) - return PTR_ERR(nhpoly1305_name); - inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); if (!inst) return -ENOMEM; @@ -536,33 +517,29 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) /* Stream cipher, e.g. "xchacha12" */ err = crypto_grab_skcipher(&ictx->streamcipher_spawn, skcipher_crypto_instance(inst), - streamcipher_name, 0, mask); + crypto_attr_alg_name(tb[1]), 0, mask); if (err) - goto out_free_inst; + goto err_free_inst; streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn); /* Block cipher, e.g. "aes" */ - err = crypto_grab_spawn(&ictx->blockcipher_spawn, - skcipher_crypto_instance(inst), - blockcipher_name, - CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK); + err = crypto_grab_cipher(&ictx->blockcipher_spawn, + skcipher_crypto_instance(inst), + crypto_attr_alg_name(tb[2]), 0, mask); if (err) - goto out_drop_streamcipher; - blockcipher_alg = ictx->blockcipher_spawn.alg; + goto err_free_inst; + blockcipher_alg = crypto_spawn_cipher_alg(&ictx->blockcipher_spawn); /* NHPoly1305 ε-∆U hash function */ - _hash_alg = crypto_alg_mod_lookup(nhpoly1305_name, - CRYPTO_ALG_TYPE_SHASH, - CRYPTO_ALG_TYPE_MASK); - if (IS_ERR(_hash_alg)) { - err = PTR_ERR(_hash_alg); - goto out_drop_blockcipher; - } - hash_alg = __crypto_shash_alg(_hash_alg); - err = crypto_init_shash_spawn(&ictx->hash_spawn, hash_alg, - skcipher_crypto_instance(inst)); + nhpoly1305_name = crypto_attr_alg_name(tb[3]); + if (nhpoly1305_name == ERR_PTR(-ENOENT)) + nhpoly1305_name = "nhpoly1305"; + err = crypto_grab_shash(&ictx->hash_spawn, + skcipher_crypto_instance(inst), + nhpoly1305_name, 0, mask); if (err) - goto out_put_hash; + goto err_free_inst; + hash_alg = crypto_spawn_shash_alg(&ictx->hash_spawn); /* Check the set of algorithms */ if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg, @@ -571,7 +548,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) streamcipher_alg->base.cra_name, blockcipher_alg->cra_name, hash_alg->base.cra_name); err = -EINVAL; - goto out_drop_hash; + goto err_free_inst; } /* Instance fields */ @@ -580,13 +557,13 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "adiantum(%s,%s)", streamcipher_alg->base.cra_name, blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME) - goto out_drop_hash; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "adiantum(%s,%s,%s)", streamcipher_alg->base.cra_driver_name, blockcipher_alg->cra_driver_name, hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto out_drop_hash; + goto err_free_inst; inst->alg.base.cra_flags = streamcipher_alg->base.cra_flags & CRYPTO_ALG_ASYNC; @@ -616,22 +593,10 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) inst->free = adiantum_free_instance; err = skcipher_register_instance(tmpl, inst); - if (err) - goto out_drop_hash; - - crypto_mod_put(_hash_alg); - return 0; - -out_drop_hash: - crypto_drop_shash(&ictx->hash_spawn); -out_put_hash: - crypto_mod_put(_hash_alg); -out_drop_blockcipher: - crypto_drop_spawn(&ictx->blockcipher_spawn); -out_drop_streamcipher: - crypto_drop_skcipher(&ictx->streamcipher_spawn); -out_free_inst: - kfree(inst); + if (err) { +err_free_inst: + adiantum_free_instance(inst); + } return err; } -- cgit v1.2.3 From 218c5035fe33df10823378353957f994d95c079b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:53 -0800 Subject: crypto: cryptd - use crypto_grab_shash() and simplify error paths Make the cryptd template (in the hash case) use the new function crypto_grab_shash() to initialize its shash spawn. This is needed to make all spawns be initialized in a consistent way. This required making cryptd_create_hash() allocate the instance directly rather than use cryptd_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/cryptd.c | 68 +++++++++++++++------------------------------------------ 1 file changed, 18 insertions(+), 50 deletions(-) (limited to 'crypto') diff --git a/crypto/cryptd.c b/crypto/cryptd.c index a03ac2878017..fb03acac7d9a 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -221,32 +221,6 @@ static int cryptd_init_instance(struct crypto_instance *inst, return 0; } -static void *cryptd_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 = cryptd_init_instance(inst, alg); - if (err) - goto out_free_inst; - -out: - return p; - -out_free_inst: - kfree(p); - p = ERR_PTR(err); - goto out; -} - static int cryptd_skcipher_setkey(struct crypto_skcipher *parent, const u8 *key, unsigned int keylen) { @@ -662,39 +636,36 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, { struct hashd_instance_ctx *ctx; struct ahash_instance *inst; - struct shash_alg *salg; - struct crypto_alg *alg; + struct shash_alg *alg; u32 type = 0; u32 mask = 0; int err; cryptd_check_internal(tb, &type, &mask); - salg = shash_attr_alg(tb[1], type, mask); - if (IS_ERR(salg)) - return PTR_ERR(salg); - - alg = &salg->base; - inst = cryptd_alloc_instance(alg, ahash_instance_headroom(), - sizeof(*ctx)); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; + inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); + if (!inst) + return -ENOMEM; ctx = ahash_instance_ctx(inst); ctx->queue = queue; - err = crypto_init_shash_spawn(&ctx->spawn, salg, - ahash_crypto_instance(inst)); + err = crypto_grab_shash(&ctx->spawn, ahash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), type, mask); if (err) - goto out_free_inst; + goto err_free_inst; + alg = crypto_spawn_shash_alg(&ctx->spawn); + + err = cryptd_init_instance(ahash_crypto_instance(inst), &alg->base); + if (err) + goto err_free_inst; inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC | - (alg->cra_flags & (CRYPTO_ALG_INTERNAL | - CRYPTO_ALG_OPTIONAL_KEY)); + (alg->base.cra_flags & (CRYPTO_ALG_INTERNAL | + CRYPTO_ALG_OPTIONAL_KEY)); - inst->alg.halg.digestsize = salg->digestsize; - inst->alg.halg.statesize = salg->statesize; + inst->alg.halg.digestsize = alg->digestsize; + inst->alg.halg.statesize = alg->statesize; inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx); inst->alg.halg.base.cra_init = cryptd_hash_init_tfm; @@ -706,19 +677,16 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, inst->alg.finup = cryptd_hash_finup_enqueue; inst->alg.export = cryptd_hash_export; inst->alg.import = cryptd_hash_import; - if (crypto_shash_alg_has_setkey(salg)) + if (crypto_shash_alg_has_setkey(alg)) inst->alg.setkey = cryptd_hash_setkey; inst->alg.digest = cryptd_hash_digest_enqueue; err = ahash_register_instance(tmpl, inst); if (err) { +err_free_inst: crypto_drop_shash(&ctx->spawn); -out_free_inst: kfree(inst); } - -out_put_alg: - crypto_mod_put(alg); return err; } -- cgit v1.2.3 From 39e7a283b3089be44a0473b77f4218791ffeba3f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:54 -0800 Subject: crypto: hmac - use crypto_grab_shash() and simplify error paths Make the hmac template use the new function crypto_grab_shash() to initialize its shash spawn. This is needed to make all spawns be initialized in a consistent way. This required making hmac_create() allocate the instance directly rather than use shash_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/hmac.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'crypto') diff --git a/crypto/hmac.c b/crypto/hmac.c index 685e49953605..0a42b7075763 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -165,6 +165,7 @@ static void hmac_exit_tfm(struct crypto_shash *parent) static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) { struct shash_instance *inst; + struct crypto_shash_spawn *spawn; struct crypto_alg *alg; struct shash_alg *salg; int err; @@ -175,31 +176,32 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) return err; - salg = shash_attr_alg(tb[1], 0, 0); - if (IS_ERR(salg)) - return PTR_ERR(salg); + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); + if (!inst) + return -ENOMEM; + spawn = shash_instance_ctx(inst); + + err = crypto_grab_shash(spawn, shash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, 0); + if (err) + goto err_free_inst; + salg = crypto_spawn_shash_alg(spawn); alg = &salg->base; /* The underlying hash algorithm must not require a key */ err = -EINVAL; if (crypto_shash_alg_needs_key(salg)) - goto out_put_alg; + goto err_free_inst; ds = salg->digestsize; ss = salg->statesize; if (ds > alg->cra_blocksize || ss < alg->cra_blocksize) - goto out_put_alg; + goto err_free_inst; - inst = shash_alloc_instance("hmac", alg); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; - - err = crypto_init_shash_spawn(shash_instance_ctx(inst), salg, - shash_crypto_instance(inst)); + err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); if (err) - goto out_free_inst; + goto err_free_inst; inst->alg.base.cra_priority = alg->cra_priority; inst->alg.base.cra_blocksize = alg->cra_blocksize; @@ -224,12 +226,9 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) err = shash_register_instance(tmpl, inst); if (err) { -out_free_inst: +err_free_inst: shash_free_instance(shash_crypto_instance(inst)); } - -out_put_alg: - crypto_mod_put(alg); return err; } -- cgit v1.2.3 From 37a861adc95ab7165a33794abda776ea1dad8475 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:55 -0800 Subject: crypto: authenc - use crypto_grab_ahash() and simplify error paths Make the authenc template use the new function crypto_grab_ahash() to initialize its ahash spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/authenc.c | 52 ++++++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) (limited to 'crypto') diff --git a/crypto/authenc.c b/crypto/authenc.c index e31bcec58564..775e7138fd10 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -375,11 +375,10 @@ static int crypto_authenc_create(struct crypto_template *tmpl, struct crypto_attr_type *algt; u32 mask; struct aead_instance *inst; + struct authenc_instance_ctx *ctx; struct hash_alg_common *auth; struct crypto_alg *auth_base; struct skcipher_alg *enc; - struct authenc_instance_ctx *ctx; - const char *enc_name; int err; algt = crypto_get_attr_type(tb); @@ -391,35 +390,22 @@ static int crypto_authenc_create(struct crypto_template *tmpl, mask = crypto_requires_sync(algt->type, algt->mask); - auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | mask); - if (IS_ERR(auth)) - return PTR_ERR(auth); - - auth_base = &auth->base; - - enc_name = crypto_attr_alg_name(tb[2]); - err = PTR_ERR(enc_name); - if (IS_ERR(enc_name)) - goto out_put_auth; - inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); - err = -ENOMEM; if (!inst) - goto out_put_auth; - + return -ENOMEM; ctx = aead_instance_ctx(inst); - err = crypto_init_ahash_spawn(&ctx->auth, auth, - aead_crypto_instance(inst)); + err = crypto_grab_ahash(&ctx->auth, aead_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, mask); if (err) goto err_free_inst; + auth = crypto_spawn_ahash_alg(&ctx->auth); + auth_base = &auth->base; err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), - enc_name, 0, mask); + crypto_attr_alg_name(tb[2]), 0, mask); if (err) - goto err_drop_auth; - + goto err_free_inst; enc = crypto_spawn_skcipher_alg(&ctx->enc); ctx->reqoff = ALIGN(2 * auth->digestsize + auth_base->cra_alignmask, @@ -430,12 +416,12 @@ static int crypto_authenc_create(struct crypto_template *tmpl, "authenc(%s,%s)", auth_base->cra_name, enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_enc; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", auth_base->cra_driver_name, enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_enc; + goto err_free_inst; inst->alg.base.cra_flags = (auth_base->cra_flags | enc->base.cra_flags) & CRYPTO_ALG_ASYNC; @@ -460,21 +446,11 @@ static int crypto_authenc_create(struct crypto_template *tmpl, inst->free = crypto_authenc_free; err = aead_register_instance(tmpl, inst); - if (err) - goto err_drop_enc; - -out: - crypto_mod_put(auth_base); - return err; - -err_drop_enc: - crypto_drop_skcipher(&ctx->enc); -err_drop_auth: - crypto_drop_ahash(&ctx->auth); + if (err) { err_free_inst: - kfree(inst); -out_put_auth: - goto out; + crypto_authenc_free(inst); + } + return err; } static struct crypto_template crypto_authenc_tmpl = { -- cgit v1.2.3 From 370738824b8e2c0ea5d8b4e4b4142fb7bab1a403 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:56 -0800 Subject: crypto: authencesn - use crypto_grab_ahash() and simplify error paths Make the authencesn template use the new function crypto_grab_ahash() to initialize its ahash spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/authencesn.c | 52 ++++++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) (limited to 'crypto') diff --git a/crypto/authencesn.c b/crypto/authencesn.c index 83bda7f905bb..589008146fce 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -393,11 +393,10 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, struct crypto_attr_type *algt; u32 mask; struct aead_instance *inst; + struct authenc_esn_instance_ctx *ctx; struct hash_alg_common *auth; struct crypto_alg *auth_base; struct skcipher_alg *enc; - struct authenc_esn_instance_ctx *ctx; - const char *enc_name; int err; algt = crypto_get_attr_type(tb); @@ -409,47 +408,34 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, mask = crypto_requires_sync(algt->type, algt->mask); - auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | mask); - if (IS_ERR(auth)) - return PTR_ERR(auth); - - auth_base = &auth->base; - - enc_name = crypto_attr_alg_name(tb[2]); - err = PTR_ERR(enc_name); - if (IS_ERR(enc_name)) - goto out_put_auth; - inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); - err = -ENOMEM; if (!inst) - goto out_put_auth; - + return -ENOMEM; ctx = aead_instance_ctx(inst); - err = crypto_init_ahash_spawn(&ctx->auth, auth, - aead_crypto_instance(inst)); + err = crypto_grab_ahash(&ctx->auth, aead_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, mask); if (err) goto err_free_inst; + auth = crypto_spawn_ahash_alg(&ctx->auth); + auth_base = &auth->base; err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), - enc_name, 0, mask); + crypto_attr_alg_name(tb[2]), 0, mask); if (err) - goto err_drop_auth; - + goto err_free_inst; enc = crypto_spawn_skcipher_alg(&ctx->enc); err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "authencesn(%s,%s)", auth_base->cra_name, enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_enc; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "authencesn(%s,%s)", auth_base->cra_driver_name, enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_enc; + goto err_free_inst; inst->alg.base.cra_flags = (auth_base->cra_flags | enc->base.cra_flags) & CRYPTO_ALG_ASYNC; @@ -475,21 +461,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl, inst->free = crypto_authenc_esn_free, err = aead_register_instance(tmpl, inst); - if (err) - goto err_drop_enc; - -out: - crypto_mod_put(auth_base); - return err; - -err_drop_enc: - crypto_drop_skcipher(&ctx->enc); -err_drop_auth: - crypto_drop_ahash(&ctx->auth); + if (err) { err_free_inst: - kfree(inst); -out_put_auth: - goto out; + crypto_authenc_esn_free(inst); + } + return err; } static struct crypto_template crypto_authenc_esn_tmpl = { -- cgit v1.2.3 From ab6ffd360d3ca3c98cba401f923b64683d666ab6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:57 -0800 Subject: crypto: gcm - use crypto_grab_ahash() and simplify error paths Make the gcm and gcm_base templates use the new function crypto_grab_ahash() to initialize their ahash spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/gcm.c | 52 ++++++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 36 deletions(-) (limited to 'crypto') diff --git a/crypto/gcm.c b/crypto/gcm.c index 72649b8cbf2a..8e5c0ac65661 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -13,7 +13,6 @@ #include #include #include -#include "internal.h" #include #include #include @@ -582,10 +581,9 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, struct crypto_attr_type *algt; u32 mask; struct aead_instance *inst; + struct gcm_instance_ctx *ctx; struct skcipher_alg *ctr; - struct crypto_alg *ghash_alg; struct hash_alg_common *ghash; - struct gcm_instance_ctx *ctx; int err; algt = crypto_get_attr_type(tb); @@ -597,35 +595,26 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, mask = crypto_requires_sync(algt->type, algt->mask); - ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type, - CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | mask); - if (IS_ERR(ghash_alg)) - return PTR_ERR(ghash_alg); - - ghash = __crypto_hash_alg_common(ghash_alg); - - err = -ENOMEM; inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); if (!inst) - goto out_put_ghash; - + return -ENOMEM; ctx = aead_instance_ctx(inst); - err = crypto_init_ahash_spawn(&ctx->ghash, ghash, - aead_crypto_instance(inst)); + + err = crypto_grab_ahash(&ctx->ghash, aead_crypto_instance(inst), + ghash_name, 0, mask); if (err) goto err_free_inst; + ghash = crypto_spawn_ahash_alg(&ctx->ghash); err = -EINVAL; if (strcmp(ghash->base.cra_name, "ghash") != 0 || ghash->digestsize != 16) - goto err_drop_ghash; + goto err_free_inst; err = crypto_grab_skcipher(&ctx->ctr, aead_crypto_instance(inst), ctr_name, 0, mask); if (err) - goto err_drop_ghash; - + goto err_free_inst; ctr = crypto_spawn_skcipher_alg(&ctx->ctr); /* The skcipher algorithm must be CTR mode, using 16-byte blocks. */ @@ -633,18 +622,18 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 || crypto_skcipher_alg_ivsize(ctr) != 16 || ctr->base.cra_blocksize != 1) - goto out_put_ctr; + goto err_free_inst; err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "gcm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME) - goto out_put_ctr; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s,%s)", ctr->base.cra_driver_name, - ghash_alg->cra_driver_name) >= + ghash->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto out_put_ctr; + goto err_free_inst; inst->alg.base.cra_flags = (ghash->base.cra_flags | ctr->base.cra_flags) & CRYPTO_ALG_ASYNC; @@ -667,20 +656,11 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, inst->free = crypto_gcm_free; err = aead_register_instance(tmpl, inst); - if (err) - goto out_put_ctr; - -out_put_ghash: - crypto_mod_put(ghash_alg); - return err; - -out_put_ctr: - crypto_drop_skcipher(&ctx->ctr); -err_drop_ghash: - crypto_drop_ahash(&ctx->ghash); + if (err) { err_free_inst: - kfree(inst); - goto out_put_ghash; + crypto_gcm_free(inst); + } + return err; } static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb) -- cgit v1.2.3 From 05b3bbb53a0570c04aba24e5849a3715e1ed4583 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:58 -0800 Subject: crypto: ccm - use crypto_grab_ahash() and simplify error paths Make the ccm and ccm_base templates use the new function crypto_grab_ahash() to initialize their ahash spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ccm.c | 61 ++++++++++++++++++++---------------------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) (limited to 'crypto') diff --git a/crypto/ccm.c b/crypto/ccm.c index 48766e81b933..a9fb46f22eaa 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -15,8 +15,6 @@ #include #include -#include "internal.h" - struct ccm_instance_ctx { struct crypto_skcipher_spawn ctr; struct crypto_ahash_spawn mac; @@ -452,10 +450,9 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, struct crypto_attr_type *algt; u32 mask; struct aead_instance *inst; + struct ccm_instance_ctx *ictx; struct skcipher_alg *ctr; - struct crypto_alg *mac_alg; struct hash_alg_common *mac; - struct ccm_instance_ctx *ictx; int err; algt = crypto_get_attr_type(tb); @@ -467,35 +464,26 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, mask = crypto_requires_sync(algt->type, algt->mask); - mac_alg = crypto_find_alg(mac_name, &crypto_ahash_type, - CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | - CRYPTO_ALG_ASYNC); - if (IS_ERR(mac_alg)) - return PTR_ERR(mac_alg); - - mac = __crypto_hash_alg_common(mac_alg); - err = -EINVAL; - if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 || - mac->digestsize != 16) - goto out_put_mac; - inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); - err = -ENOMEM; if (!inst) - goto out_put_mac; - + return -ENOMEM; ictx = aead_instance_ctx(inst); - err = crypto_init_ahash_spawn(&ictx->mac, mac, - aead_crypto_instance(inst)); + + err = crypto_grab_ahash(&ictx->mac, aead_crypto_instance(inst), + mac_name, 0, CRYPTO_ALG_ASYNC); if (err) goto err_free_inst; + mac = crypto_spawn_ahash_alg(&ictx->mac); + + err = -EINVAL; + if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 || + mac->digestsize != 16) + goto err_free_inst; err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst), ctr_name, 0, mask); if (err) - goto err_drop_mac; - + goto err_free_inst; ctr = crypto_spawn_skcipher_alg(&ictx->ctr); /* The skcipher algorithm must be CTR mode, using 16-byte blocks. */ @@ -503,21 +491,21 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 || crypto_skcipher_alg_ivsize(ctr) != 16 || ctr->base.cra_blocksize != 1) - goto err_drop_ctr; + goto err_free_inst; /* ctr and cbcmac must use the same underlying block cipher. */ if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0) - goto err_drop_ctr; + goto err_free_inst; err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_ctr; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)", ctr->base.cra_driver_name, mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_ctr; + goto err_free_inst; inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_priority = (mac->base.cra_priority + @@ -539,20 +527,11 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, inst->free = crypto_ccm_free; err = aead_register_instance(tmpl, inst); - if (err) - goto err_drop_ctr; - -out_put_mac: - crypto_mod_put(mac_alg); - return err; - -err_drop_ctr: - crypto_drop_skcipher(&ictx->ctr); -err_drop_mac: - crypto_drop_ahash(&ictx->mac); + if (err) { err_free_inst: - kfree(inst); - goto out_put_mac; + crypto_ccm_free(inst); + } + return err; } static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb) -- cgit v1.2.3 From c282586fc341f9af741928f74a90163d26a1b347 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:58:59 -0800 Subject: crypto: chacha20poly1305 - use crypto_grab_ahash() and simplify error paths Make the rfc7539 and rfc7539esp templates use the new function crypto_grab_ahash() to initialize their ahash spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/chacha20poly1305.c | 84 +++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 57 deletions(-) (limited to 'crypto') diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index 09d5a34ab339..ccaea5cb66d1 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -16,8 +16,6 @@ #include #include -#include "internal.h" - struct chachapoly_instance_ctx { struct crypto_skcipher_spawn chacha; struct crypto_ahash_spawn poly; @@ -560,11 +558,9 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, struct crypto_attr_type *algt; u32 mask; struct aead_instance *inst; - struct skcipher_alg *chacha; - struct crypto_alg *poly; - struct hash_alg_common *poly_hash; struct chachapoly_instance_ctx *ctx; - const char *chacha_name, *poly_name; + struct skcipher_alg *chacha; + struct hash_alg_common *poly; int err; if (ivsize > CHACHAPOLY_IV_SIZE) @@ -579,68 +575,51 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, mask = crypto_requires_sync(algt->type, algt->mask); - chacha_name = crypto_attr_alg_name(tb[1]); - if (IS_ERR(chacha_name)) - return PTR_ERR(chacha_name); - poly_name = crypto_attr_alg_name(tb[2]); - if (IS_ERR(poly_name)) - return PTR_ERR(poly_name); - - poly = crypto_find_alg(poly_name, &crypto_ahash_type, - CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_AHASH_MASK | mask); - if (IS_ERR(poly)) - return PTR_ERR(poly); - poly_hash = __crypto_hash_alg_common(poly); - - err = -EINVAL; - if (poly_hash->digestsize != POLY1305_DIGEST_SIZE) - goto out_put_poly; - - err = -ENOMEM; inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); if (!inst) - goto out_put_poly; - + return -ENOMEM; ctx = aead_instance_ctx(inst); ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize; - err = crypto_init_ahash_spawn(&ctx->poly, poly_hash, - aead_crypto_instance(inst)); - if (err) - goto err_free_inst; err = crypto_grab_skcipher(&ctx->chacha, aead_crypto_instance(inst), - chacha_name, 0, mask); + crypto_attr_alg_name(tb[1]), 0, mask); if (err) - goto err_drop_poly; - + goto err_free_inst; chacha = crypto_spawn_skcipher_alg(&ctx->chacha); + err = crypto_grab_ahash(&ctx->poly, aead_crypto_instance(inst), + crypto_attr_alg_name(tb[2]), 0, mask); + if (err) + goto err_free_inst; + poly = crypto_spawn_ahash_alg(&ctx->poly); + err = -EINVAL; + if (poly->digestsize != POLY1305_DIGEST_SIZE) + goto err_free_inst; /* Need 16-byte IV size, including Initial Block Counter value */ if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE) - goto out_drop_chacha; + goto err_free_inst; /* Not a stream cipher? */ if (chacha->base.cra_blocksize != 1) - goto out_drop_chacha; + goto err_free_inst; err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s,%s)", name, chacha->base.cra_name, - poly->cra_name) >= CRYPTO_MAX_ALG_NAME) - goto out_drop_chacha; + poly->base.cra_name) >= CRYPTO_MAX_ALG_NAME) + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s,%s)", name, chacha->base.cra_driver_name, - poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto out_drop_chacha; + poly->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) + goto err_free_inst; - inst->alg.base.cra_flags = (chacha->base.cra_flags | poly->cra_flags) & - CRYPTO_ALG_ASYNC; + inst->alg.base.cra_flags = (chacha->base.cra_flags | + poly->base.cra_flags) & CRYPTO_ALG_ASYNC; inst->alg.base.cra_priority = (chacha->base.cra_priority + - poly->cra_priority) / 2; + poly->base.cra_priority) / 2; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = chacha->base.cra_alignmask | - poly->cra_alignmask; + poly->base.cra_alignmask; inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) + ctx->saltlen; inst->alg.ivsize = ivsize; @@ -656,20 +635,11 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, inst->free = chachapoly_free; err = aead_register_instance(tmpl, inst); - if (err) - goto out_drop_chacha; - -out_put_poly: - crypto_mod_put(poly); - return err; - -out_drop_chacha: - crypto_drop_skcipher(&ctx->chacha); -err_drop_poly: - crypto_drop_ahash(&ctx->poly); + if (err) { err_free_inst: - kfree(inst); - goto out_put_poly; + chachapoly_free(inst); + } + return err; } static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb) -- cgit v1.2.3 From aacd5b4cfb87306888eb9e3612cb90afbb2ecba5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:00 -0800 Subject: crypto: skcipher - use crypto_grab_cipher() and simplify error paths Make skcipher_alloc_instance_simple() use the new function crypto_grab_cipher() to initialize its cipher spawn. This is needed to make all spawns be initialized in a consistent way. Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/skcipher.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'crypto') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 15c033c960f7..950ff1438131 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -908,7 +908,7 @@ static void skcipher_exit_tfm_simple(struct crypto_skcipher *tfm) static void skcipher_free_instance_simple(struct skcipher_instance *inst) { - crypto_drop_spawn(skcipher_instance_ctx(inst)); + crypto_drop_cipher(skcipher_instance_ctx(inst)); kfree(inst); } @@ -932,10 +932,10 @@ struct skcipher_instance *skcipher_alloc_instance_simple( struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; - struct crypto_alg *cipher_alg; - struct skcipher_instance *inst; - struct crypto_spawn *spawn; u32 mask; + struct skcipher_instance *inst; + struct crypto_cipher_spawn *spawn; + struct crypto_alg *cipher_alg; int err; algt = crypto_get_attr_type(tb); @@ -945,32 +945,25 @@ struct skcipher_instance *skcipher_alloc_instance_simple( if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) return ERR_PTR(-EINVAL); - mask = CRYPTO_ALG_TYPE_MASK | - crypto_requires_off(algt->type, algt->mask, - CRYPTO_ALG_NEED_FALLBACK); - - cipher_alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, mask); - if (IS_ERR(cipher_alg)) - return ERR_CAST(cipher_alg); + mask = crypto_requires_off(algt->type, algt->mask, + CRYPTO_ALG_NEED_FALLBACK); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); - if (!inst) { - err = -ENOMEM; - goto err_put_cipher_alg; - } + if (!inst) + return ERR_PTR(-ENOMEM); spawn = skcipher_instance_ctx(inst); - err = crypto_inst_setname(skcipher_crypto_instance(inst), tmpl->name, - cipher_alg); + err = crypto_grab_cipher(spawn, skcipher_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, mask); if (err) goto err_free_inst; + cipher_alg = crypto_spawn_cipher_alg(spawn); - spawn->dropref = true; - err = crypto_init_spawn(spawn, cipher_alg, - skcipher_crypto_instance(inst), - CRYPTO_ALG_TYPE_MASK); + err = crypto_inst_setname(skcipher_crypto_instance(inst), tmpl->name, + cipher_alg); if (err) goto err_free_inst; + inst->free = skcipher_free_instance_simple; /* Default algorithm properties, can be overridden */ @@ -990,9 +983,7 @@ struct skcipher_instance *skcipher_alloc_instance_simple( return inst; err_free_inst: - kfree(inst); -err_put_cipher_alg: - crypto_mod_put(cipher_alg); + skcipher_free_instance_simple(inst); return ERR_PTR(err); } EXPORT_SYMBOL_GPL(skcipher_alloc_instance_simple); -- cgit v1.2.3 From 166729709775263066af1747c8029e960a20910a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:01 -0800 Subject: crypto: cbcmac - use crypto_grab_cipher() and simplify error paths Make the cbcmac template use the new function crypto_grab_cipher() to initialize its cipher spawn. This is needed to make all spawns be initialized in a consistent way. This required making cbcmac_create() allocate the instance directly rather than use shash_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ccm.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'crypto') diff --git a/crypto/ccm.c b/crypto/ccm.c index a9fb46f22eaa..411c3973b95c 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -887,6 +887,7 @@ static void cbcmac_exit_tfm(struct crypto_tfm *tfm) static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb) { struct shash_instance *inst; + struct crypto_cipher_spawn *spawn; struct crypto_alg *alg; int err; @@ -894,21 +895,20 @@ static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) return err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK); - if (IS_ERR(alg)) - return PTR_ERR(alg); + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); + if (!inst) + return -ENOMEM; + spawn = shash_instance_ctx(inst); - inst = shash_alloc_instance("cbcmac", alg); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; + err = crypto_grab_cipher(spawn, shash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, 0); + if (err) + goto err_free_inst; + alg = crypto_spawn_cipher_alg(spawn); - err = crypto_init_spawn(shash_instance_ctx(inst), alg, - shash_crypto_instance(inst), - CRYPTO_ALG_TYPE_MASK); + err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); if (err) - goto out_free_inst; + goto err_free_inst; inst->alg.base.cra_priority = alg->cra_priority; inst->alg.base.cra_blocksize = 1; @@ -928,13 +928,10 @@ static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.setkey = crypto_cbcmac_digest_setkey; err = shash_register_instance(tmpl, inst); - -out_free_inst: - if (err) + if (err) { +err_free_inst: shash_free_instance(shash_crypto_instance(inst)); - -out_put_alg: - crypto_mod_put(alg); + } return err; } -- cgit v1.2.3 From 1d0459cd83f5426d668ec3304a35f9dbeee6296b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:02 -0800 Subject: crypto: cmac - use crypto_grab_cipher() and simplify error paths Make the cmac template use the new function crypto_grab_cipher() to initialize its cipher spawn. This is needed to make all spawns be initialized in a consistent way. This required making cmac_create() allocate the instance directly rather than use shash_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/cmac.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'crypto') diff --git a/crypto/cmac.c b/crypto/cmac.c index 0928aebc6205..c6bf78b5321a 100644 --- a/crypto/cmac.c +++ b/crypto/cmac.c @@ -222,6 +222,7 @@ static void cmac_exit_tfm(struct crypto_tfm *tfm) static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) { struct shash_instance *inst; + struct crypto_cipher_spawn *spawn; struct crypto_alg *alg; unsigned long alignmask; int err; @@ -230,10 +231,16 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) return err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK); - if (IS_ERR(alg)) - return PTR_ERR(alg); + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); + if (!inst) + return -ENOMEM; + spawn = shash_instance_ctx(inst); + + err = crypto_grab_cipher(spawn, shash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, 0); + if (err) + goto err_free_inst; + alg = crypto_spawn_cipher_alg(spawn); switch (alg->cra_blocksize) { case 16: @@ -241,19 +248,12 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) break; default: err = -EINVAL; - goto out_put_alg; + goto err_free_inst; } - inst = shash_alloc_instance("cmac", alg); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; - - err = crypto_init_spawn(shash_instance_ctx(inst), alg, - shash_crypto_instance(inst), - CRYPTO_ALG_TYPE_MASK); + err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); if (err) - goto out_free_inst; + goto err_free_inst; alignmask = alg->cra_alignmask; inst->alg.base.cra_alignmask = alignmask; @@ -282,12 +282,9 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) err = shash_register_instance(tmpl, inst); if (err) { -out_free_inst: +err_free_inst: shash_free_instance(shash_crypto_instance(inst)); } - -out_put_alg: - crypto_mod_put(alg); return err; } -- cgit v1.2.3 From 3b4e73d8ca810f63af05f367c576f0b33920657b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:03 -0800 Subject: crypto: vmac - use crypto_grab_cipher() and simplify error paths Make the vmac64 template use the new function crypto_grab_cipher() to initialize its cipher spawn. This is needed to make all spawns be initialized in a consistent way. This required making vmac_create() allocate the instance directly rather than use shash_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/vmac.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'crypto') diff --git a/crypto/vmac.c b/crypto/vmac.c index 0bbb34dc87c4..9b000aaa20a8 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -618,6 +618,7 @@ static void vmac_exit_tfm(struct crypto_tfm *tfm) static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) { struct shash_instance *inst; + struct crypto_cipher_spawn *spawn; struct crypto_alg *alg; int err; @@ -625,25 +626,24 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) return err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK); - if (IS_ERR(alg)) - return PTR_ERR(alg); + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); + if (!inst) + return -ENOMEM; + spawn = shash_instance_ctx(inst); + + err = crypto_grab_cipher(spawn, shash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, 0); + if (err) + goto err_free_inst; + alg = crypto_spawn_cipher_alg(spawn); err = -EINVAL; if (alg->cra_blocksize != VMAC_NONCEBYTES) - goto out_put_alg; + goto err_free_inst; - inst = shash_alloc_instance(tmpl->name, alg); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; - - err = crypto_init_spawn(shash_instance_ctx(inst), alg, - shash_crypto_instance(inst), - CRYPTO_ALG_TYPE_MASK); + err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); if (err) - goto out_free_inst; + goto err_free_inst; inst->alg.base.cra_priority = alg->cra_priority; inst->alg.base.cra_blocksize = alg->cra_blocksize; @@ -662,12 +662,9 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) err = shash_register_instance(tmpl, inst); if (err) { -out_free_inst: +err_free_inst: shash_free_instance(shash_crypto_instance(inst)); } - -out_put_alg: - crypto_mod_put(alg); return err; } -- cgit v1.2.3 From 1e212a6a562f781f00cba6c7ece93817857e0f32 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:04 -0800 Subject: crypto: xcbc - use crypto_grab_cipher() and simplify error paths Make the xcbc template use the new function crypto_grab_cipher() to initialize its cipher spawn. This is needed to make all spawns be initialized in a consistent way. This required making xcbc_create() allocate the instance directly rather than use shash_alloc_instance(). Also simplify the error handling by taking advantage of crypto_drop_*() now accepting (as a no-op) spawns that haven't been initialized yet, and by taking advantage of crypto_grab_*() now handling ERR_PTR() names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/xcbc.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'crypto') diff --git a/crypto/xcbc.c b/crypto/xcbc.c index 0bb26e8f6f5a..9b97fa511f10 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -188,6 +188,7 @@ static void xcbc_exit_tfm(struct crypto_tfm *tfm) static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct shash_instance *inst; + struct crypto_cipher_spawn *spawn; struct crypto_alg *alg; unsigned long alignmask; int err; @@ -196,28 +197,24 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) if (err) return err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK); - if (IS_ERR(alg)) - return PTR_ERR(alg); + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); + if (!inst) + return -ENOMEM; + spawn = shash_instance_ctx(inst); - switch(alg->cra_blocksize) { - case XCBC_BLOCKSIZE: - break; - default: - goto out_put_alg; - } + err = crypto_grab_cipher(spawn, shash_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, 0); + if (err) + goto err_free_inst; + alg = crypto_spawn_cipher_alg(spawn); - inst = shash_alloc_instance("xcbc", alg); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; + err = -EINVAL; + if (alg->cra_blocksize != XCBC_BLOCKSIZE) + goto err_free_inst; - err = crypto_init_spawn(shash_instance_ctx(inst), alg, - shash_crypto_instance(inst), - CRYPTO_ALG_TYPE_MASK); + err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); if (err) - goto out_free_inst; + goto err_free_inst; alignmask = alg->cra_alignmask | 3; inst->alg.base.cra_alignmask = alignmask; @@ -244,12 +241,9 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) err = shash_register_instance(tmpl, inst); if (err) { -out_free_inst: +err_free_inst: shash_free_instance(shash_crypto_instance(inst)); } - -out_put_alg: - crypto_mod_put(alg); return err; } -- cgit v1.2.3 From d5ed3b65f7012a6592809f7f928f3e3660df8fd9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:05 -0800 Subject: crypto: cipher - make crypto_spawn_cipher() take a crypto_cipher_spawn Now that all users of single-block cipher spawns have been converted to use 'struct crypto_cipher_spawn' rather than the less specifically typed 'struct crypto_spawn', make crypto_spawn_cipher() take a pointer to a 'struct crypto_cipher_spawn' rather than a 'struct crypto_spawn'. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/adiantum.c | 2 +- crypto/ccm.c | 2 +- crypto/cmac.c | 2 +- crypto/skcipher.c | 2 +- crypto/vmac.c | 2 +- crypto/xcbc.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 5b8aa14ccb55..4d7a6cac82ed 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -408,7 +408,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm) if (IS_ERR(streamcipher)) return PTR_ERR(streamcipher); - blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn.base); + blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn); if (IS_ERR(blockcipher)) { err = PTR_ERR(blockcipher); goto err_free_streamcipher; diff --git a/crypto/ccm.c b/crypto/ccm.c index 411c3973b95c..f4abaefd9df5 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -866,7 +866,7 @@ static int cbcmac_init_tfm(struct crypto_tfm *tfm) { struct crypto_cipher *cipher; struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); cipher = crypto_spawn_cipher(spawn); diff --git a/crypto/cmac.c b/crypto/cmac.c index c6bf78b5321a..58dc644416bb 100644 --- a/crypto/cmac.c +++ b/crypto/cmac.c @@ -201,7 +201,7 @@ static int cmac_init_tfm(struct crypto_tfm *tfm) { struct crypto_cipher *cipher; struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); struct cmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); cipher = crypto_spawn_cipher(spawn); diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 950ff1438131..42add1e0814f 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -887,7 +887,7 @@ static int skcipher_setkey_simple(struct crypto_skcipher *tfm, const u8 *key, static int skcipher_init_tfm_simple(struct crypto_skcipher *tfm) { struct skcipher_instance *inst = skcipher_alg_instance(tfm); - struct crypto_spawn *spawn = skcipher_instance_ctx(inst); + struct crypto_cipher_spawn *spawn = skcipher_instance_ctx(inst); struct skcipher_ctx_simple *ctx = crypto_skcipher_ctx(tfm); struct crypto_cipher *cipher; diff --git a/crypto/vmac.c b/crypto/vmac.c index 9b000aaa20a8..28358a6aef9f 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -596,7 +596,7 @@ static int vmac_final(struct shash_desc *desc, u8 *out) static int vmac_init_tfm(struct crypto_tfm *tfm) { struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); - struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm); struct crypto_cipher *cipher; diff --git a/crypto/xcbc.c b/crypto/xcbc.c index 9b97fa511f10..9265e00ea663 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -167,7 +167,7 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm) { struct crypto_cipher *cipher; struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm); cipher = crypto_spawn_cipher(spawn); -- cgit v1.2.3 From 629f1afc15ee8f34ec67bef0c33b9bccca7eeecc Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:06 -0800 Subject: crypto: algapi - remove obsoleted instance creation helpers Remove lots of helper functions that were previously used for instantiating crypto templates, but are now unused: - crypto_get_attr_alg() and similar functions looked up an inner algorithm directly from a template parameter. These were replaced with getting the algorithm's name, then calling crypto_grab_*(). - crypto_init_spawn2() and similar functions initialized a spawn, given an algorithm. Similarly, these were replaced with crypto_grab_*(). - crypto_alloc_instance() and similar functions allocated an instance with a single spawn, given the inner algorithm. These aren't useful anymore since crypto_grab_*() need the instance allocated first. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ahash.c | 25 ------------------------- crypto/algapi.c | 57 --------------------------------------------------------- crypto/shash.c | 19 ------------------- 3 files changed, 101 deletions(-) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index e98a1398ed7f..2b8449fdb93c 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -655,31 +655,6 @@ int ahash_register_instance(struct crypto_template *tmpl, } EXPORT_SYMBOL_GPL(ahash_register_instance); -void ahash_free_instance(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(ahash_instance(inst)); -} -EXPORT_SYMBOL_GPL(ahash_free_instance); - -int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, - struct hash_alg_common *alg, - struct crypto_instance *inst) -{ - return crypto_init_spawn2(&spawn->base, &alg->base, inst, - &crypto_ahash_type); -} -EXPORT_SYMBOL_GPL(crypto_init_ahash_spawn); - -struct hash_alg_common *ahash_attr_alg(struct rtattr *rta, u32 type, u32 mask) -{ - struct crypto_alg *alg; - - alg = crypto_attr_alg2(rta, &crypto_ahash_type, type, mask); - return IS_ERR(alg) ? ERR_CAST(alg) : __crypto_hash_alg_common(alg); -} -EXPORT_SYMBOL_GPL(ahash_attr_alg); - bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg) { struct crypto_alg *alg = &halg->base; diff --git a/crypto/algapi.c b/crypto/algapi.c index a25ce02918f8..f66a4ff57e6e 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -697,23 +697,6 @@ int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, } EXPORT_SYMBOL_GPL(crypto_init_spawn); -int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg, - struct crypto_instance *inst, - const struct crypto_type *frontend) -{ - int err = -EINVAL; - - if ((alg->cra_flags ^ frontend->type) & frontend->maskset) - goto out; - - spawn->frontend = frontend; - err = crypto_init_spawn(spawn, alg, inst, frontend->maskset); - -out: - return err; -} -EXPORT_SYMBOL_GPL(crypto_init_spawn2); - int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask) { @@ -876,20 +859,6 @@ const char *crypto_attr_alg_name(struct rtattr *rta) } EXPORT_SYMBOL_GPL(crypto_attr_alg_name); -struct crypto_alg *crypto_attr_alg2(struct rtattr *rta, - const struct crypto_type *frontend, - u32 type, u32 mask) -{ - const char *name; - - name = crypto_attr_alg_name(rta); - if (IS_ERR(name)) - return ERR_CAST(name); - - return crypto_find_alg(name, frontend, type, mask); -} -EXPORT_SYMBOL_GPL(crypto_attr_alg2); - int crypto_attr_u32(struct rtattr *rta, u32 *num) { struct crypto_attr_u32 *nu32; @@ -923,32 +892,6 @@ int crypto_inst_setname(struct crypto_instance *inst, const char *name, } EXPORT_SYMBOL_GPL(crypto_inst_setname); -void *crypto_alloc_instance(const char *name, struct crypto_alg *alg, - unsigned int head) -{ - struct crypto_instance *inst; - char *p; - int err; - - p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn), - GFP_KERNEL); - if (!p) - return ERR_PTR(-ENOMEM); - - inst = (void *)(p + head); - - err = crypto_inst_setname(inst, name, alg); - if (err) - goto err_free_inst; - - return p; - -err_free_inst: - kfree(p); - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(crypto_alloc_instance); - void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen) { INIT_LIST_HEAD(&queue->list); diff --git a/crypto/shash.c b/crypto/shash.c index e0872ac2729a..4d6ccb59e126 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -584,24 +584,5 @@ void shash_free_instance(struct crypto_instance *inst) } EXPORT_SYMBOL_GPL(shash_free_instance); -int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn, - struct shash_alg *alg, - struct crypto_instance *inst) -{ - return crypto_init_spawn2(&spawn->base, &alg->base, inst, - &crypto_shash_type); -} -EXPORT_SYMBOL_GPL(crypto_init_shash_spawn); - -struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask) -{ - struct crypto_alg *alg; - - alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask); - return IS_ERR(alg) ? ERR_CAST(alg) : - container_of(alg, struct shash_alg, base); -} -EXPORT_SYMBOL_GPL(shash_attr_alg); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Synchronous cryptographic hash type"); -- cgit v1.2.3 From 6d1b41fce0aa916efd1ce0728e1e4bd20a3642d5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:07 -0800 Subject: crypto: ahash - unexport crypto_ahash_type Now that all the templates that need ahash spawns have been converted to use crypto_grab_ahash() rather than look up the algorithm directly, crypto_ahash_type is no longer used outside of ahash.c. Make it static. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ahash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index 2b8449fdb93c..c77717fcea8e 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -23,6 +23,8 @@ #include "internal.h" +static const struct crypto_type crypto_ahash_type; + struct ahash_request_priv { crypto_completion_t complete; void *data; @@ -542,7 +544,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) __crypto_hash_alg_common(alg)->digestsize); } -const struct crypto_type crypto_ahash_type = { +static const struct crypto_type crypto_ahash_type = { .extsize = crypto_ahash_extsize, .init_tfm = crypto_ahash_init_tfm, #ifdef CONFIG_PROC_FS @@ -554,7 +556,6 @@ const struct crypto_type crypto_ahash_type = { .type = CRYPTO_ALG_TYPE_AHASH, .tfmsize = offsetof(struct crypto_ahash, base), }; -EXPORT_SYMBOL_GPL(crypto_ahash_type); int crypto_grab_ahash(struct crypto_ahash_spawn *spawn, struct crypto_instance *inst, -- cgit v1.2.3 From aed11cf57ddb24aa97ca3b55c9e26c37759c4baa Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 19:59:08 -0800 Subject: crypto: algapi - fold crypto_init_spawn() into crypto_grab_spawn() Now that crypto_init_spawn() is only called by crypto_grab_spawn(), simplify things by moving its functionality into crypto_grab_spawn(). In the process of doing this, also be more consistent about when the spawn and instance are updated, and remove the crypto_spawn::dropref flag since now it's always set. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/algapi.c | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index f66a4ff57e6e..72592795c7e7 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -629,8 +629,7 @@ int crypto_register_instance(struct crypto_template *tmpl, spawn->inst = inst; spawn->registered = true; - if (spawn->dropref) - crypto_mod_put(spawn->alg); + crypto_mod_put(spawn->alg); spawn = next; } @@ -672,47 +671,33 @@ void crypto_unregister_instance(struct crypto_instance *inst) } EXPORT_SYMBOL_GPL(crypto_unregister_instance); -int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, - struct crypto_instance *inst, u32 mask) +int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, + const char *name, u32 type, u32 mask) { + struct crypto_alg *alg; int err = -EAGAIN; if (WARN_ON_ONCE(inst == NULL)) return -EINVAL; - spawn->next = inst->spawns; - inst->spawns = spawn; + /* Allow the result of crypto_attr_alg_name() to be passed directly */ + if (IS_ERR(name)) + return PTR_ERR(name); - spawn->mask = mask; + alg = crypto_find_alg(name, spawn->frontend, type, mask); + if (IS_ERR(alg)) + return PTR_ERR(alg); down_write(&crypto_alg_sem); if (!crypto_is_moribund(alg)) { list_add(&spawn->list, &alg->cra_users); spawn->alg = alg; + spawn->mask = mask; + spawn->next = inst->spawns; + inst->spawns = spawn; err = 0; } up_write(&crypto_alg_sem); - - return err; -} -EXPORT_SYMBOL_GPL(crypto_init_spawn); - -int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, - const char *name, u32 type, u32 mask) -{ - struct crypto_alg *alg; - int err; - - /* Allow the result of crypto_attr_alg_name() to be passed directly */ - if (IS_ERR(name)) - return PTR_ERR(name); - - alg = crypto_find_alg(name, spawn->frontend, type, mask); - if (IS_ERR(alg)) - return PTR_ERR(alg); - - spawn->dropref = true; - err = crypto_init_spawn(spawn, alg, inst, mask); if (err) crypto_mod_put(alg); return err; @@ -729,7 +714,7 @@ void crypto_drop_spawn(struct crypto_spawn *spawn) list_del(&spawn->list); up_write(&crypto_alg_sem); - if (spawn->dropref && !spawn->registered) + if (!spawn->registered) crypto_mod_put(spawn->alg); } EXPORT_SYMBOL_GPL(crypto_drop_spawn); -- cgit v1.2.3 From 48fb3e5785be7ef69a43c04f617a1c05000ee2d0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:35 -0800 Subject: crypto: hash - add support for new way of freeing instances Add support to shash and ahash for the new way of freeing instances (already used for skcipher, aead, and akcipher) where a ->free() method is installed to the instance struct itself. These methods are more strongly-typed than crypto_template::free(), which they replace. This will allow removing support for the old way of freeing instances. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ahash.c | 13 +++++++++++++ crypto/shash.c | 13 +++++++++++++ 2 files changed, 26 insertions(+) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index c77717fcea8e..61e374d76b04 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -511,6 +511,18 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg) return crypto_alg_extsize(alg); } +static void crypto_ahash_free_instance(struct crypto_instance *inst) +{ + struct ahash_instance *ahash = ahash_instance(inst); + + if (!ahash->free) { + inst->tmpl->free(inst); + return; + } + + ahash->free(ahash); +} + #ifdef CONFIG_NET static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg) { @@ -547,6 +559,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) static const struct crypto_type crypto_ahash_type = { .extsize = crypto_ahash_extsize, .init_tfm = crypto_ahash_init_tfm, + .free = crypto_ahash_free_instance, #ifdef CONFIG_PROC_FS .show = crypto_ahash_show, #endif diff --git a/crypto/shash.c b/crypto/shash.c index 4d6ccb59e126..2f6adb49727b 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -423,6 +423,18 @@ static int crypto_shash_init_tfm(struct crypto_tfm *tfm) return 0; } +static void crypto_shash_free_instance(struct crypto_instance *inst) +{ + struct shash_instance *shash = shash_instance(inst); + + if (!shash->free) { + inst->tmpl->free(inst); + return; + } + + shash->free(shash); +} + #ifdef CONFIG_NET static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) { @@ -459,6 +471,7 @@ static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) static const struct crypto_type crypto_shash_type = { .extsize = crypto_alg_extsize, .init_tfm = crypto_shash_init_tfm, + .free = crypto_shash_free_instance, #ifdef CONFIG_PROC_FS .show = crypto_shash_show, #endif -- cgit v1.2.3 From 0f8f6d86d415f9d88dc0f7847f11d0c52dba1965 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:36 -0800 Subject: crypto: geniv - convert to new way of freeing instances Convert the "seqiv" template to the new way of freeing instances where a ->free() method is installed to the instance struct itself. Also remove the unused implementation of the old way of freeing instances from the "echainiv" template, since it's already using the new way too. In doing this, also simplify the code by making the helper function aead_geniv_alloc() install the ->free() method, instead of making seqiv and echainiv do this themselves. This is analogous to how skcipher_alloc_instance_simple() works. This will allow removing support for the old way of freeing instances. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/echainiv.c | 20 ++++---------------- crypto/geniv.c | 15 ++++++++------- crypto/seqiv.c | 20 ++++---------------- 3 files changed, 16 insertions(+), 39 deletions(-) (limited to 'crypto') diff --git a/crypto/echainiv.c b/crypto/echainiv.c index a49cbf7b0929..4a2f02baba14 100644 --- a/crypto/echainiv.c +++ b/crypto/echainiv.c @@ -133,29 +133,17 @@ static int echainiv_aead_create(struct crypto_template *tmpl, inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); inst->alg.base.cra_ctxsize += inst->alg.ivsize; - inst->free = aead_geniv_free; - err = aead_register_instance(tmpl, inst); - if (err) - goto free_inst; - -out: - return err; - + if (err) { free_inst: - aead_geniv_free(inst); - goto out; -} - -static void echainiv_free(struct crypto_instance *inst) -{ - aead_geniv_free(aead_instance(inst)); + inst->free(inst); + } + return err; } static struct crypto_template echainiv_tmpl = { .name = "echainiv", .create = echainiv_aead_create, - .free = echainiv_free, .module = THIS_MODULE, }; diff --git a/crypto/geniv.c b/crypto/geniv.c index 7afa48414f3a..dbcc640274cd 100644 --- a/crypto/geniv.c +++ b/crypto/geniv.c @@ -32,6 +32,12 @@ static int aead_geniv_setauthsize(struct crypto_aead *tfm, return crypto_aead_setauthsize(ctx->child, authsize); } +static void aead_geniv_free(struct aead_instance *inst) +{ + crypto_drop_aead(aead_instance_ctx(inst)); + kfree(inst); +} + struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, struct rtattr **tb, u32 type, u32 mask) { @@ -100,6 +106,8 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, inst->alg.ivsize = ivsize; inst->alg.maxauthsize = maxauthsize; + inst->free = aead_geniv_free; + out: return inst; @@ -112,13 +120,6 @@ err_free_inst: } EXPORT_SYMBOL_GPL(aead_geniv_alloc); -void aead_geniv_free(struct aead_instance *inst) -{ - crypto_drop_aead(aead_instance_ctx(inst)); - kfree(inst); -} -EXPORT_SYMBOL_GPL(aead_geniv_free); - int aead_init_geniv(struct crypto_aead *aead) { struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead); diff --git a/crypto/seqiv.c b/crypto/seqiv.c index 96d222c32acc..f124b9b54e15 100644 --- a/crypto/seqiv.c +++ b/crypto/seqiv.c @@ -18,8 +18,6 @@ #include #include -static void seqiv_free(struct crypto_instance *inst); - static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err) { struct aead_request *subreq = aead_request_ctx(req); @@ -159,15 +157,11 @@ static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.base.cra_ctxsize += inst->alg.ivsize; err = aead_register_instance(tmpl, inst); - if (err) - goto free_inst; - -out: - return err; - + if (err) { free_inst: - aead_geniv_free(inst); - goto out; + inst->free(inst); + } + return err; } static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb) @@ -184,15 +178,9 @@ static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb) return seqiv_aead_create(tmpl, tb); } -static void seqiv_free(struct crypto_instance *inst) -{ - aead_geniv_free(aead_instance(inst)); -} - static struct crypto_template seqiv_tmpl = { .name = "seqiv", .create = seqiv_create, - .free = seqiv_free, .module = THIS_MODULE, }; -- cgit v1.2.3 From 758ec5ac5be8923b92c5214d91f6ba1236b95356 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:37 -0800 Subject: crypto: cryptd - convert to new way of freeing instances Convert the "cryptd" template to the new way of freeing instances, where a ->free() method is installed to the instance struct itself. This replaces the weakly-typed method crypto_template::free(). This will allow removing support for the old way of freeing instances. Note that the 'default' case in cryptd_free() was already unreachable. So, we aren't missing anything by keeping only the ahash and aead parts. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/cryptd.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'crypto') diff --git a/crypto/cryptd.c b/crypto/cryptd.c index fb03acac7d9a..d94c75c840a5 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -631,6 +631,14 @@ static int cryptd_hash_import(struct ahash_request *req, const void *in) return crypto_shash_import(desc, in); } +static void cryptd_hash_free(struct ahash_instance *inst) +{ + struct hashd_instance_ctx *ctx = ahash_instance_ctx(inst); + + crypto_drop_shash(&ctx->spawn); + kfree(inst); +} + static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, struct cryptd_queue *queue) { @@ -681,6 +689,8 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, inst->alg.setkey = cryptd_hash_setkey; inst->alg.digest = cryptd_hash_digest_enqueue; + inst->free = cryptd_hash_free; + err = ahash_register_instance(tmpl, inst); if (err) { err_free_inst: @@ -808,6 +818,14 @@ static void cryptd_aead_exit_tfm(struct crypto_aead *tfm) crypto_free_aead(ctx->child); } +static void cryptd_aead_free(struct aead_instance *inst) +{ + struct aead_instance_ctx *ctx = aead_instance_ctx(inst); + + crypto_drop_aead(&ctx->aead_spawn); + kfree(inst); +} + static int cryptd_create_aead(struct crypto_template *tmpl, struct rtattr **tb, struct cryptd_queue *queue) @@ -857,6 +875,8 @@ static int cryptd_create_aead(struct crypto_template *tmpl, inst->alg.encrypt = cryptd_aead_encrypt_enqueue; inst->alg.decrypt = cryptd_aead_decrypt_enqueue; + inst->free = cryptd_aead_free; + err = aead_register_instance(tmpl, inst); if (err) { out_drop_aead: @@ -889,31 +909,9 @@ static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb) return -EINVAL; } -static void cryptd_free(struct crypto_instance *inst) -{ - struct cryptd_instance_ctx *ctx = crypto_instance_ctx(inst); - struct hashd_instance_ctx *hctx = crypto_instance_ctx(inst); - struct aead_instance_ctx *aead_ctx = 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; - case CRYPTO_ALG_TYPE_AEAD: - crypto_drop_aead(&aead_ctx->aead_spawn); - kfree(aead_instance(inst)); - return; - default: - crypto_drop_spawn(&ctx->spawn); - kfree(inst); - } -} - static struct crypto_template cryptd_tmpl = { .name = "cryptd", .create = cryptd_create, - .free = cryptd_free, .module = THIS_MODULE, }; -- cgit v1.2.3 From a39c66cc2f6108c8346dc882bdcf72861aaca956 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:38 -0800 Subject: crypto: shash - convert shash_free_instance() to new style Convert shash_free_instance() and its users to the new way of freeing instances, where a ->free() method is installed to the instance struct itself. This replaces the weakly-typed method crypto_template::free(). This will allow removing support for the old way of freeing instances. Also give shash_free_instance() a more descriptive name to reflect that it's only for instances with a single spawn, not for any instance. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/ccm.c | 5 +++-- crypto/cmac.c | 5 +++-- crypto/hmac.c | 5 +++-- crypto/shash.c | 8 ++++---- crypto/vmac.c | 5 +++-- crypto/xcbc.c | 5 +++-- 6 files changed, 19 insertions(+), 14 deletions(-) (limited to 'crypto') diff --git a/crypto/ccm.c b/crypto/ccm.c index f4abaefd9df5..241ecdc5c4e0 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -927,10 +927,12 @@ static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.final = crypto_cbcmac_digest_final; inst->alg.setkey = crypto_cbcmac_digest_setkey; + inst->free = shash_free_singlespawn_instance; + err = shash_register_instance(tmpl, inst); if (err) { err_free_inst: - shash_free_instance(shash_crypto_instance(inst)); + shash_free_singlespawn_instance(inst); } return err; } @@ -939,7 +941,6 @@ static struct crypto_template crypto_ccm_tmpls[] = { { .name = "cbcmac", .create = cbcmac_create, - .free = shash_free_instance, .module = THIS_MODULE, }, { .name = "ccm_base", diff --git a/crypto/cmac.c b/crypto/cmac.c index 58dc644416bb..143a6544c873 100644 --- a/crypto/cmac.c +++ b/crypto/cmac.c @@ -280,10 +280,12 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.final = crypto_cmac_digest_final; inst->alg.setkey = crypto_cmac_digest_setkey; + inst->free = shash_free_singlespawn_instance; + err = shash_register_instance(tmpl, inst); if (err) { err_free_inst: - shash_free_instance(shash_crypto_instance(inst)); + shash_free_singlespawn_instance(inst); } return err; } @@ -291,7 +293,6 @@ err_free_inst: static struct crypto_template crypto_cmac_tmpl = { .name = "cmac", .create = cmac_create, - .free = shash_free_instance, .module = THIS_MODULE, }; diff --git a/crypto/hmac.c b/crypto/hmac.c index 0a42b7075763..e38bfb948278 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -224,10 +224,12 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.init_tfm = hmac_init_tfm; inst->alg.exit_tfm = hmac_exit_tfm; + inst->free = shash_free_singlespawn_instance; + err = shash_register_instance(tmpl, inst); if (err) { err_free_inst: - shash_free_instance(shash_crypto_instance(inst)); + shash_free_singlespawn_instance(inst); } return err; } @@ -235,7 +237,6 @@ err_free_inst: static struct crypto_template hmac_tmpl = { .name = "hmac", .create = hmac_create, - .free = shash_free_instance, .module = THIS_MODULE, }; diff --git a/crypto/shash.c b/crypto/shash.c index 2f6adb49727b..e05e75b0f402 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -590,12 +590,12 @@ int shash_register_instance(struct crypto_template *tmpl, } EXPORT_SYMBOL_GPL(shash_register_instance); -void shash_free_instance(struct crypto_instance *inst) +void shash_free_singlespawn_instance(struct shash_instance *inst) { - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(shash_instance(inst)); + crypto_drop_spawn(shash_instance_ctx(inst)); + kfree(inst); } -EXPORT_SYMBOL_GPL(shash_free_instance); +EXPORT_SYMBOL_GPL(shash_free_singlespawn_instance); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Synchronous cryptographic hash type"); diff --git a/crypto/vmac.c b/crypto/vmac.c index 28358a6aef9f..2d906830df96 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -660,10 +660,12 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.final = vmac_final; inst->alg.setkey = vmac_setkey; + inst->free = shash_free_singlespawn_instance; + err = shash_register_instance(tmpl, inst); if (err) { err_free_inst: - shash_free_instance(shash_crypto_instance(inst)); + shash_free_singlespawn_instance(inst); } return err; } @@ -671,7 +673,6 @@ err_free_inst: static struct crypto_template vmac64_tmpl = { .name = "vmac64", .create = vmac_create, - .free = shash_free_instance, .module = THIS_MODULE, }; diff --git a/crypto/xcbc.c b/crypto/xcbc.c index 9265e00ea663..598ec88abf0f 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -239,10 +239,12 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.final = crypto_xcbc_digest_final; inst->alg.setkey = crypto_xcbc_digest_setkey; + inst->free = shash_free_singlespawn_instance; + err = shash_register_instance(tmpl, inst); if (err) { err_free_inst: - shash_free_instance(shash_crypto_instance(inst)); + shash_free_singlespawn_instance(inst); } return err; } @@ -250,7 +252,6 @@ err_free_inst: static struct crypto_template crypto_xcbc_tmpl = { .name = "xcbc", .create = xcbc_create, - .free = shash_free_instance, .module = THIS_MODULE, }; -- cgit v1.2.3 From a24a1fd731274ebbca873000e2c7fbe8224ae4c8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:39 -0800 Subject: crypto: algapi - remove crypto_template::{alloc,free}() Now that all templates provide a ->create() method which creates an instance, installs a strongly-typed ->free() method directly to it, and registers it, the older ->alloc() and ->free() methods in 'struct crypto_template' are no longer used. Remove them. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/aead.c | 5 ----- crypto/ahash.c | 5 ----- crypto/algapi.c | 5 ----- crypto/algboss.c | 12 +----------- crypto/shash.c | 5 ----- 5 files changed, 1 insertion(+), 31 deletions(-) (limited to 'crypto') diff --git a/crypto/aead.c b/crypto/aead.c index 02a0db076d7e..7707d3223101 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -185,11 +185,6 @@ static void crypto_aead_free_instance(struct crypto_instance *inst) { struct aead_instance *aead = aead_instance(inst); - if (!aead->free) { - inst->tmpl->free(inst); - return; - } - aead->free(aead); } diff --git a/crypto/ahash.c b/crypto/ahash.c index 61e374d76b04..cd5d9847d513 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -515,11 +515,6 @@ static void crypto_ahash_free_instance(struct crypto_instance *inst) { struct ahash_instance *ahash = ahash_instance(inst); - if (!ahash->free) { - inst->tmpl->free(inst); - return; - } - ahash->free(ahash); } diff --git a/crypto/algapi.c b/crypto/algapi.c index 72592795c7e7..69605e21af92 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -65,11 +65,6 @@ static int crypto_check_alg(struct crypto_alg *alg) static void crypto_free_instance(struct crypto_instance *inst) { - if (!inst->alg.cra_type->free) { - inst->tmpl->free(inst); - return; - } - inst->alg.cra_type->free(inst); } diff --git a/crypto/algboss.c b/crypto/algboss.c index a62149d6c839..535f1f87e6c1 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c @@ -58,7 +58,6 @@ static int cryptomgr_probe(void *data) { struct cryptomgr_param *param = data; struct crypto_template *tmpl; - struct crypto_instance *inst; int err; tmpl = crypto_lookup_template(param->template); @@ -66,16 +65,7 @@ static int cryptomgr_probe(void *data) goto out; do { - if (tmpl->create) { - err = tmpl->create(tmpl, param->tb); - continue; - } - - inst = tmpl->alloc(param->tb); - if (IS_ERR(inst)) - err = PTR_ERR(inst); - else if ((err = crypto_register_instance(tmpl, inst))) - tmpl->free(inst); + err = tmpl->create(tmpl, param->tb); } while (err == -EAGAIN && !signal_pending(current)); crypto_tmpl_put(tmpl); diff --git a/crypto/shash.c b/crypto/shash.c index e05e75b0f402..70faf28b2d14 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -427,11 +427,6 @@ static void crypto_shash_free_instance(struct crypto_instance *inst) { struct shash_instance *shash = shash_instance(inst); - if (!shash->free) { - inst->tmpl->free(inst); - return; - } - shash->free(shash); } -- cgit v1.2.3 From d4fdc2dfaa755e0bf22de6a2774cac2e5ae45cf4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Jan 2020 20:04:40 -0800 Subject: crypto: algapi - enforce that all instances have a ->free() method All instances need to have a ->free() method, but people could forget to set it and then not notice if the instance is never unregistered. To help detect this bug earlier, don't allow an instance without a ->free() method to be registered, and complain loudly if someone tries to do it. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/aead.c | 3 +++ crypto/ahash.c | 3 +++ crypto/akcipher.c | 2 ++ crypto/shash.c | 3 +++ crypto/skcipher.c | 3 +++ 5 files changed, 14 insertions(+) (limited to 'crypto') diff --git a/crypto/aead.c b/crypto/aead.c index 7707d3223101..16991095270d 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -288,6 +288,9 @@ int aead_register_instance(struct crypto_template *tmpl, { int err; + if (WARN_ON(!inst->free)) + return -EINVAL; + err = aead_prepare_alg(&inst->alg); if (err) return err; diff --git a/crypto/ahash.c b/crypto/ahash.c index cd5d9847d513..68a0f0cb75c4 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -656,6 +656,9 @@ int ahash_register_instance(struct crypto_template *tmpl, { int err; + if (WARN_ON(!inst->free)) + return -EINVAL; + err = ahash_prepare_alg(&inst->alg); if (err) return err; diff --git a/crypto/akcipher.c b/crypto/akcipher.c index eeed6c151d2f..f866085c8a4a 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -147,6 +147,8 @@ EXPORT_SYMBOL_GPL(crypto_unregister_akcipher); int akcipher_register_instance(struct crypto_template *tmpl, struct akcipher_instance *inst) { + if (WARN_ON(!inst->free)) + return -EINVAL; akcipher_prepare_alg(&inst->alg); return crypto_register_instance(tmpl, akcipher_crypto_instance(inst)); } diff --git a/crypto/shash.c b/crypto/shash.c index 70faf28b2d14..c075b26c2a1d 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -577,6 +577,9 @@ int shash_register_instance(struct crypto_template *tmpl, { int err; + if (WARN_ON(!inst->free)) + return -EINVAL; + err = shash_prepare_alg(&inst->alg); if (err) return err; diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 42add1e0814f..7221def7b9a7 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -865,6 +865,9 @@ int skcipher_register_instance(struct crypto_template *tmpl, { int err; + if (WARN_ON(!inst->free)) + return -EINVAL; + err = skcipher_prepare_alg(&inst->alg); if (err) return err; -- cgit v1.2.3 From 1c08a104360f3e18f4ee6346c21cc3923efb952e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 5 Jan 2020 22:40:46 -0500 Subject: crypto: poly1305 - add new 32 and 64-bit generic versions These two C implementations from Zinc -- a 32x32 one and a 64x64 one, depending on the platform -- come from Andrew Moon's public domain poly1305-donna portable code, modified for usage in the kernel. The precomputation in the 32-bit version and the use of 64x64 multiplies in the 64-bit version make these perform better than the code it replaces. Moon's code is also very widespread and has received many eyeballs of scrutiny. There's a bit of interference between the x86 implementation, which relies on internal details of the old scalar implementation. In the next commit, the x86 implementation will be replaced with a faster one that doesn't rely on this, so none of this matters much. But for now, to keep this passing the tests, we inline the bits of the old implementation that the x86 implementation relied on. Also, since we now support a slightly larger key space, via the union, some offsets had to be fixed up. Nonce calculation was folded in with the emit function, to take advantage of 64x64 arithmetic. However, Adiantum appeared to rely on no nonce handling in emit, so this path was conditionalized. We also introduced a new struct, poly1305_core_key, to represent the precise amount of space that particular implementation uses. Testing with kbench9000, depending on the CPU, the update function for the 32x32 version has been improved by 4%-7%, and for the 64x64 by 19%-30%. The 32x32 gains are small, but I think there's great value in having a parallel implementation to the 64x64 one so that the two can be compared side-by-side as nice stand-alone units. Signed-off-by: Jason A. Donenfeld Signed-off-by: Herbert Xu --- crypto/adiantum.c | 4 ++-- crypto/nhpoly1305.c | 2 +- crypto/poly1305_generic.c | 25 ++++++++++++++++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 4d7a6cac82ed..53d5e705a425 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -70,7 +70,7 @@ struct adiantum_tfm_ctx { struct crypto_skcipher *streamcipher; struct crypto_cipher *blockcipher; struct crypto_shash *hash; - struct poly1305_key header_hash_key; + struct poly1305_core_key header_hash_key; }; struct adiantum_request_ctx { @@ -239,7 +239,7 @@ static void adiantum_hash_header(struct skcipher_request *req) poly1305_core_blocks(&state, &tctx->header_hash_key, req->iv, TWEAK_SIZE / POLY1305_BLOCK_SIZE, 1); - poly1305_core_emit(&state, &rctx->header_hash); + poly1305_core_emit(&state, NULL, &rctx->header_hash); } /* Hash the left-hand part (the "bulk") of the message using NHPoly1305 */ diff --git a/crypto/nhpoly1305.c b/crypto/nhpoly1305.c index f6b6a52092b4..8a3006c3b51b 100644 --- a/crypto/nhpoly1305.c +++ b/crypto/nhpoly1305.c @@ -210,7 +210,7 @@ int crypto_nhpoly1305_final_helper(struct shash_desc *desc, u8 *dst, nh_t nh_fn) if (state->nh_remaining) process_nh_hash_value(state, key); - poly1305_core_emit(&state->poly_state, dst); + poly1305_core_emit(&state->poly_state, NULL, dst); return 0; } EXPORT_SYMBOL(crypto_nhpoly1305_final_helper); diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c index 21edbd8c99fb..94af47eb6fa6 100644 --- a/crypto/poly1305_generic.c +++ b/crypto/poly1305_generic.c @@ -31,6 +31,29 @@ static int crypto_poly1305_init(struct shash_desc *desc) return 0; } +static unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen) +{ + if (!dctx->sset) { + if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) { + poly1305_core_setkey(&dctx->core_r, src); + src += POLY1305_BLOCK_SIZE; + srclen -= POLY1305_BLOCK_SIZE; + dctx->rset = 2; + } + if (srclen >= POLY1305_BLOCK_SIZE) { + dctx->s[0] = get_unaligned_le32(src + 0); + dctx->s[1] = get_unaligned_le32(src + 4); + dctx->s[2] = get_unaligned_le32(src + 8); + dctx->s[3] = get_unaligned_le32(src + 12); + src += POLY1305_BLOCK_SIZE; + srclen -= POLY1305_BLOCK_SIZE; + dctx->sset = true; + } + } + return srclen; +} + static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src, unsigned int srclen) { @@ -42,7 +65,7 @@ static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src, srclen = datalen; } - poly1305_core_blocks(&dctx->h, dctx->r, src, + poly1305_core_blocks(&dctx->h, &dctx->core_r, src, srclen / POLY1305_BLOCK_SIZE, 1); } -- cgit v1.2.3 From ab3d436bf3e9d05f58ceaa85ff7475bfcd6e45af Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 12 Jan 2020 17:58:58 +0100 Subject: crypto: essiv - fix AEAD capitalization and preposition use in help text "AEAD" is capitalized everywhere else. Use "an" when followed by a written or spoken vowel. Fixes: be1eb7f78aa8fbe3 ("crypto: essiv - create wrapper template for ESSIV generation") Signed-off-by: Geert Uytterhoeven Signed-off-by: Herbert Xu --- crypto/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index 5575d48473bd..cdb51d4272d0 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -511,10 +511,10 @@ config CRYPTO_ESSIV encryption. This driver implements a crypto API template that can be - instantiated either as a skcipher or as a aead (depending on the + instantiated either as an skcipher or as an AEAD (depending on the type of the first template argument), and which defers encryption and decryption requests to the encapsulated cipher after applying - ESSIV to the input IV. Note that in the aead case, it is assumed + ESSIV to the input IV. Note that in the AEAD case, it is assumed that the keys are presented in the same format used by the authenc template, and that the IV appears at the end of the authenticated associated data (AAD) region (which is how dm-crypt uses it.) -- cgit v1.2.3