diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-05 20:09:55 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-05 20:09:55 +0300 |
commit | 63bdf4284c38a48af21745ceb148a087b190cd21 (patch) | |
tree | ffbf9e69ed457e776db0317903ccb0addbd1b276 /crypto/ctr.c | |
parent | 6456300356433873309a1cae6aa05e77d6b59153 (diff) | |
parent | 0918f18c7179e8cdf718d01531a81b28130b4217 (diff) | |
download | linux-63bdf4284c38a48af21745ceb148a087b190cd21.tar.xz |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu:
"API:
- Add helper for simple skcipher modes.
- Add helper to register multiple templates.
- Set CRYPTO_TFM_NEED_KEY when setkey fails.
- Require neither or both of export/import in shash.
- AEAD decryption test vectors are now generated from encryption
ones.
- New option CONFIG_CRYPTO_MANAGER_EXTRA_TESTS that includes random
fuzzing.
Algorithms:
- Conversions to skcipher and helper for many templates.
- Add more test vectors for nhpoly1305 and adiantum.
Drivers:
- Add crypto4xx prng support.
- Add xcbc/cmac/ecb support in caam.
- Add AES support for Exynos5433 in s5p.
- Remove sha384/sha512 from artpec7 as hardware cannot do partial
hash"
[ There is a merge of the Freescale SoC tree in order to pull in changes
required by patches to the caam/qi2 driver. ]
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (174 commits)
crypto: s5p - add AES support for Exynos5433
dt-bindings: crypto: document Exynos5433 SlimSSS
crypto: crypto4xx - add missing of_node_put after of_device_is_available
crypto: cavium/zip - fix collision with generic cra_driver_name
crypto: af_alg - use struct_size() in sock_kfree_s()
crypto: caam - remove redundant likely/unlikely annotation
crypto: s5p - update iv after AES-CBC op end
crypto: x86/poly1305 - Clear key material from stack in SSE2 variant
crypto: caam - generate hash keys in-place
crypto: caam - fix DMA mapping xcbc key twice
crypto: caam - fix hash context DMA unmap size
hwrng: bcm2835 - fix probe as platform device
crypto: s5p-sss - Use AES_BLOCK_SIZE define instead of number
crypto: stm32 - drop pointless static qualifier in stm32_hash_remove()
crypto: chelsio - Fixed Traffic Stall
crypto: marvell - Remove set but not used variable 'ivsize'
crypto: ccp - Update driver messages to remove some confusion
crypto: adiantum - add 1536 and 4096-byte test vectors
crypto: nhpoly1305 - add a test vector with len % 16 != 0
crypto: arm/aes-ce - update IV after partial final CTR block
...
Diffstat (limited to 'crypto/ctr.c')
-rw-r--r-- | crypto/ctr.c | 200 |
1 files changed, 54 insertions, 146 deletions
diff --git a/crypto/ctr.c b/crypto/ctr.c index 30f3946efc6d..ec8f8b67473a 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -17,14 +17,8 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/random.h> -#include <linux/scatterlist.h> #include <linux/slab.h> -struct crypto_ctr_ctx { - struct crypto_cipher *child; -}; - struct crypto_rfc3686_ctx { struct crypto_skcipher *child; u8 nonce[CTR_RFC3686_NONCE_SIZE]; @@ -35,24 +29,7 @@ struct crypto_rfc3686_req_ctx { struct skcipher_request subreq CRYPTO_MINALIGN_ATTR; }; -static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, - unsigned int keylen) -{ - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent); - struct crypto_cipher *child = ctx->child; - int err; - - crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & - CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(child, key, keylen); - crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; -} - -static void crypto_ctr_crypt_final(struct blkcipher_walk *walk, +static void crypto_ctr_crypt_final(struct skcipher_walk *walk, struct crypto_cipher *tfm) { unsigned int bsize = crypto_cipher_blocksize(tfm); @@ -70,7 +47,7 @@ static void crypto_ctr_crypt_final(struct blkcipher_walk *walk, crypto_inc(ctrblk, bsize); } -static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, +static int crypto_ctr_crypt_segment(struct skcipher_walk *walk, struct crypto_cipher *tfm) { void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = @@ -96,7 +73,7 @@ static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, return nbytes; } -static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, +static int crypto_ctr_crypt_inplace(struct skcipher_walk *walk, struct crypto_cipher *tfm) { void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = @@ -123,138 +100,77 @@ static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, return nbytes; } -static int crypto_ctr_crypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static int crypto_ctr_crypt(struct skcipher_request *req) { - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - unsigned int bsize = crypto_cipher_blocksize(child); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); + const unsigned int bsize = crypto_cipher_blocksize(cipher); + struct skcipher_walk walk; + unsigned int nbytes; int err; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, bsize); + err = skcipher_walk_virt(&walk, req, false); while (walk.nbytes >= bsize) { if (walk.src.virt.addr == walk.dst.virt.addr) - nbytes = crypto_ctr_crypt_inplace(&walk, child); + nbytes = crypto_ctr_crypt_inplace(&walk, cipher); else - nbytes = crypto_ctr_crypt_segment(&walk, child); + nbytes = crypto_ctr_crypt_segment(&walk, cipher); - err = blkcipher_walk_done(desc, &walk, nbytes); + err = skcipher_walk_done(&walk, nbytes); } if (walk.nbytes) { - crypto_ctr_crypt_final(&walk, child); - err = blkcipher_walk_done(desc, &walk, 0); + crypto_ctr_crypt_final(&walk, cipher); + err = skcipher_walk_done(&walk, 0); } return err; } -static int crypto_ctr_init_tfm(struct crypto_tfm *tfm) -{ - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - struct crypto_cipher *cipher; - - cipher = crypto_spawn_cipher(spawn); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - ctx->child = cipher; - - return 0; -} - -static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm) -{ - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - - crypto_free_cipher(ctx->child); -} - -static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb) +static int crypto_ctr_create(struct crypto_template *tmpl, struct rtattr **tb) { - struct crypto_instance *inst; - struct crypto_attr_type *algt; + struct skcipher_instance *inst; struct crypto_alg *alg; - u32 mask; int err; - err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); - if (err) - return ERR_PTR(err); - - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return ERR_CAST(algt); - - mask = CRYPTO_ALG_TYPE_MASK | - crypto_requires_off(algt->type, algt->mask, - CRYPTO_ALG_NEED_FALLBACK); - - alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, mask); - if (IS_ERR(alg)) - return ERR_CAST(alg); + inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); + if (IS_ERR(inst)) + return PTR_ERR(inst); /* Block size must be >= 4 bytes. */ err = -EINVAL; if (alg->cra_blocksize < 4) - goto out_put_alg; + goto out_free_inst; /* If this is false we'd fail the alignment of crypto_inc. */ if (alg->cra_blocksize % 4) - goto out_put_alg; - - inst = crypto_alloc_instance("ctr", alg); - if (IS_ERR(inst)) - goto out; - - inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = 1; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_blkcipher_type; - - inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; - inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; - inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; + goto out_free_inst; - inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx); + /* CTR mode is a stream cipher. */ + inst->alg.base.cra_blocksize = 1; - inst->alg.cra_init = crypto_ctr_init_tfm; - inst->alg.cra_exit = crypto_ctr_exit_tfm; + /* + * To simplify the implementation, configure the skcipher walk to only + * give a partial block at the very end, never earlier. + */ + inst->alg.chunksize = alg->cra_blocksize; - inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey; - inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt; - inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt; + inst->alg.encrypt = crypto_ctr_crypt; + inst->alg.decrypt = crypto_ctr_crypt; -out: - crypto_mod_put(alg); - return inst; + err = skcipher_register_instance(tmpl, inst); + if (err) + goto out_free_inst; + goto out_put_alg; +out_free_inst: + inst->free(inst); out_put_alg: - inst = ERR_PTR(err); - goto out; -} - -static void crypto_ctr_free(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); + crypto_mod_put(alg); + return err; } -static struct crypto_template crypto_ctr_tmpl = { - .name = "ctr", - .alloc = crypto_ctr_alloc, - .free = crypto_ctr_free, - .module = THIS_MODULE, -}; - static int crypto_rfc3686_setkey(struct crypto_skcipher *parent, const u8 *key, unsigned int keylen) { @@ -444,42 +360,34 @@ err_free_inst: goto out; } -static struct crypto_template crypto_rfc3686_tmpl = { - .name = "rfc3686", - .create = crypto_rfc3686_create, - .module = THIS_MODULE, +static struct crypto_template crypto_ctr_tmpls[] = { + { + .name = "ctr", + .create = crypto_ctr_create, + .module = THIS_MODULE, + }, { + .name = "rfc3686", + .create = crypto_rfc3686_create, + .module = THIS_MODULE, + }, }; static int __init crypto_ctr_module_init(void) { - int err; - - err = crypto_register_template(&crypto_ctr_tmpl); - if (err) - goto out; - - err = crypto_register_template(&crypto_rfc3686_tmpl); - if (err) - goto out_drop_ctr; - -out: - return err; - -out_drop_ctr: - crypto_unregister_template(&crypto_ctr_tmpl); - goto out; + return crypto_register_templates(crypto_ctr_tmpls, + ARRAY_SIZE(crypto_ctr_tmpls)); } static void __exit crypto_ctr_module_exit(void) { - crypto_unregister_template(&crypto_rfc3686_tmpl); - crypto_unregister_template(&crypto_ctr_tmpl); + crypto_unregister_templates(crypto_ctr_tmpls, + ARRAY_SIZE(crypto_ctr_tmpls)); } module_init(crypto_ctr_module_init); module_exit(crypto_ctr_module_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CTR Counter block mode"); +MODULE_DESCRIPTION("CTR block cipher mode of operation"); MODULE_ALIAS_CRYPTO("rfc3686"); MODULE_ALIAS_CRYPTO("ctr"); |