From 39e1ee011f42dbbcb0210c73ea728ae54cf63b06 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 29 Aug 2007 19:27:26 +0800 Subject: [CRYPTO] api: Add support for multiple template parameters This patch adds support for having multiple parameters to a template, separated by a comma. It also adds support for integer parameters in addition to the current algorithm parameter type. This will be used by the authenc template which will have four parameters: the authentication algorithm, the encryption algorithm, the authentication size and the encryption key length. Signed-off-by: Herbert Xu --- crypto/algapi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'crypto/algapi.c') diff --git a/crypto/algapi.c b/crypto/algapi.c index 38aa9e99470..d9559609b52 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -439,13 +439,15 @@ EXPORT_SYMBOL_GPL(crypto_unregister_notifier); struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb) { - struct rtattr *rta = tb[CRYPTOA_TYPE - 1]; + struct rtattr *rta = tb[0]; struct crypto_attr_type *algt; if (!rta) return ERR_PTR(-ENOENT); if (RTA_PAYLOAD(rta) < sizeof(*algt)) return ERR_PTR(-EINVAL); + if (rta->rta_type != CRYPTOA_TYPE) + return ERR_PTR(-EINVAL); algt = RTA_DATA(rta); @@ -470,13 +472,15 @@ EXPORT_SYMBOL_GPL(crypto_check_attr_type); struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask) { - struct rtattr *rta = tb[CRYPTOA_ALG - 1]; + struct rtattr *rta = tb[1]; struct crypto_attr_alg *alga; if (!rta) return ERR_PTR(-ENOENT); if (RTA_PAYLOAD(rta) < sizeof(*alga)) return ERR_PTR(-EINVAL); + if (rta->rta_type != CRYPTOA_ALG) + return ERR_PTR(-EINVAL); alga = RTA_DATA(rta); alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0; -- cgit v1.2.3-70-g09d2 From 3c09f17c3d11f3e98928f55b600e6de22f58017a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 30 Aug 2007 16:24:15 +0800 Subject: [CRYPTO] aead: Add authenc This patch adds the authenc algorithm which constructs an AEAD algorithm from an asynchronous block cipher and a hash. The construction is done by concatenating the encrypted result from the cipher with the output from the hash, as is used by the IPsec ESP protocol. The authenc algorithm exists as a template with four parameters: authenc(auth, authsize, enc, enckeylen). The authentication algorithm, the authentication size (i.e., truncating the output of the authentication algorithm), the encryption algorithm, and the encryption key length. Both the size field and the key length field are in bytes. For example, AES-128 with SHA1-HMAC would be represented by authenc(hmac(sha1), 12, cbc(aes), 16) The key for the authenc algorithm is the concatenation of the keys for the authentication algorithm with the encryption algorithm. For the above example, if a key of length 36 bytes is given, then hmac(sha1) would receive the first 20 bytes while the last 16 would be given to cbc(aes). Signed-off-by: Herbert Xu --- crypto/Kconfig | 8 + crypto/Makefile | 1 + crypto/algapi.c | 23 ++- crypto/authenc.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++ include/crypto/algapi.h | 44 +++++- 5 files changed, 472 insertions(+), 4 deletions(-) create mode 100644 crypto/authenc.c (limited to 'crypto/algapi.c') diff --git a/crypto/Kconfig b/crypto/Kconfig index f42bc7715f4..05f46dfdf18 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -483,6 +483,14 @@ config CRYPTO_TEST help Quick & dirty crypto test module. +config CRYPTO_AUTHENC + tristate "Authenc support" + select CRYPTO_AEAD + select CRYPTO_MANAGER + help + Authenc: Combined mode wrapper for IPsec. + This is required for IPSec. + source "drivers/crypto/Kconfig" endif # if CRYPTO diff --git a/crypto/Makefile b/crypto/Makefile index 7e1d5b89903..da256665aae 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_CRYPTO_SEED) += seed.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o +obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o diff --git a/crypto/algapi.c b/crypto/algapi.c index d9559609b52..d891f56f0e8 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -470,9 +470,8 @@ int crypto_check_attr_type(struct rtattr **tb, u32 type) } EXPORT_SYMBOL_GPL(crypto_check_attr_type); -struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask) +struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask) { - struct rtattr *rta = tb[1]; struct crypto_attr_alg *alga; if (!rta) @@ -487,7 +486,25 @@ struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask) return crypto_alg_mod_lookup(alga->name, type, mask); } -EXPORT_SYMBOL_GPL(crypto_get_attr_alg); +EXPORT_SYMBOL_GPL(crypto_attr_alg); + +int crypto_attr_u32(struct rtattr *rta, u32 *num) +{ + struct crypto_attr_u32 *nu32; + + if (!rta) + return -ENOENT; + if (RTA_PAYLOAD(rta) < sizeof(*nu32)) + return -EINVAL; + if (rta->rta_type != CRYPTOA_U32) + return -EINVAL; + + nu32 = RTA_DATA(rta); + *num = nu32->num; + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_attr_u32); struct crypto_instance *crypto_alloc_instance(const char *name, struct crypto_alg *alg) diff --git a/crypto/authenc.c b/crypto/authenc.c new file mode 100644 index 00000000000..86b3ac88eab --- /dev/null +++ b/crypto/authenc.c @@ -0,0 +1,400 @@ +/* + * Authenc: Simple AEAD wrapper for IPsec + * + * Copyright (c) 2007 Herbert Xu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "scatterwalk.h" + +struct authenc_instance_ctx { + struct crypto_spawn auth; + struct crypto_spawn enc; + + unsigned int authsize; + unsigned int enckeylen; +}; + +struct crypto_authenc_ctx { + spinlock_t auth_lock; + struct crypto_hash *auth; + struct crypto_ablkcipher *enc; +}; + +static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, + unsigned int keylen) +{ + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + unsigned int enckeylen = ictx->enckeylen; + unsigned int authkeylen; + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct crypto_ablkcipher *enc = ctx->enc; + int err = -EINVAL; + + if (keylen < enckeylen) { + crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); + goto out; + } + authkeylen = keylen - enckeylen; + + crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); + crypto_hash_set_flags(auth, crypto_aead_get_flags(authenc) & + CRYPTO_TFM_REQ_MASK); + err = crypto_hash_setkey(auth, key, authkeylen); + crypto_aead_set_flags(authenc, crypto_hash_get_flags(auth) & + CRYPTO_TFM_RES_MASK); + + if (err) + goto out; + + crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); + crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) & + CRYPTO_TFM_REQ_MASK); + err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen); + crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) & + CRYPTO_TFM_RES_MASK); + +out: + return err; +} + +static int crypto_authenc_hash(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct hash_desc desc = { + .tfm = auth, + }; + u8 *hash = aead_request_ctx(req); + struct scatterlist *dst; + unsigned int cryptlen; + int err; + + hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), + crypto_hash_alignmask(auth) + 1); + + spin_lock_bh(&ctx->auth_lock); + err = crypto_hash_init(&desc); + if (err) + goto auth_unlock; + + err = crypto_hash_update(&desc, req->assoc, req->assoclen); + if (err) + goto auth_unlock; + + cryptlen = req->cryptlen; + dst = req->dst; + err = crypto_hash_update(&desc, dst, cryptlen); + if (err) + goto auth_unlock; + + err = crypto_hash_final(&desc, hash); +auth_unlock: + spin_unlock_bh(&ctx->auth_lock); + + if (err) + return err; + + scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1); + return 0; +} + +static void crypto_authenc_encrypt_done(struct crypto_async_request *req, + int err) +{ + if (!err) + err = crypto_authenc_hash(req->data); + + aead_request_complete(req->data, err); +} + +static int crypto_authenc_encrypt(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct ablkcipher_request *abreq = aead_request_ctx(req); + int err; + + ablkcipher_request_set_tfm(abreq, ctx->enc); + ablkcipher_request_set_callback(abreq, aead_request_flags(req), + crypto_authenc_encrypt_done, req); + ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, + req->iv); + + err = crypto_ablkcipher_encrypt(abreq); + if (err) + return err; + + return crypto_authenc_hash(req); +} + +static int crypto_authenc_verify(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct authenc_instance_ctx *ictx = + crypto_instance_ctx(crypto_aead_alg_instance(authenc)); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct crypto_hash *auth = ctx->auth; + struct hash_desc desc = { + .tfm = auth, + .flags = aead_request_flags(req), + }; + u8 *ohash = aead_request_ctx(req); + u8 *ihash; + struct scatterlist *src; + unsigned int cryptlen; + unsigned int authsize; + int err; + + ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), + crypto_hash_alignmask(auth) + 1); + ihash = ohash + crypto_hash_digestsize(auth); + + spin_lock_bh(&ctx->auth_lock); + err = crypto_hash_init(&desc); + if (err) + goto auth_unlock; + + err = crypto_hash_update(&desc, req->assoc, req->assoclen); + if (err) + goto auth_unlock; + + cryptlen = req->cryptlen; + src = req->src; + err = crypto_hash_update(&desc, src, cryptlen); + if (err) + goto auth_unlock; + + err = crypto_hash_final(&desc, ohash); +auth_unlock: + spin_unlock_bh(&ctx->auth_lock); + + if (err) + return err; + + authsize = ictx->authsize; + scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); + return memcmp(ihash, ohash, authsize) ? -EINVAL : 0; +} + +static void crypto_authenc_decrypt_done(struct crypto_async_request *req, + int err) +{ + aead_request_complete(req->data, err); +} + +static int crypto_authenc_decrypt(struct aead_request *req) +{ + struct crypto_aead *authenc = crypto_aead_reqtfm(req); + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); + struct ablkcipher_request *abreq = aead_request_ctx(req); + int err; + + err = crypto_authenc_verify(req); + if (err) + return err; + + ablkcipher_request_set_tfm(abreq, ctx->enc); + ablkcipher_request_set_callback(abreq, aead_request_flags(req), + crypto_authenc_decrypt_done, req); + ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, + req->iv); + + return crypto_ablkcipher_decrypt(abreq); +} + +static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst); + struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_hash *auth; + struct crypto_ablkcipher *enc; + unsigned int digestsize; + int err; + + auth = crypto_spawn_hash(&ictx->auth); + if (IS_ERR(auth)) + return PTR_ERR(auth); + + err = -EINVAL; + digestsize = crypto_hash_digestsize(auth); + if (ictx->authsize > digestsize) + goto err_free_hash; + + enc = crypto_spawn_ablkcipher(&ictx->enc); + err = PTR_ERR(enc); + if (IS_ERR(enc)) + goto err_free_hash; + + ctx->auth = auth; + ctx->enc = enc; + tfm->crt_aead.reqsize = max_t(unsigned int, + (crypto_hash_alignmask(auth) & + ~(crypto_tfm_ctx_alignment() - 1)) + + digestsize * 2, + sizeof(struct ablkcipher_request) + + crypto_ablkcipher_reqsize(enc)); + + spin_lock_init(&ctx->auth_lock); + + return 0; + +err_free_hash: + crypto_free_hash(auth); + return err; +} + +static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_hash(ctx->auth); + crypto_free_ablkcipher(ctx->enc); +} + +static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) +{ + struct crypto_instance *inst; + struct crypto_alg *auth; + struct crypto_alg *enc; + struct authenc_instance_ctx *ctx; + unsigned int authsize; + unsigned int enckeylen; + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); + if (err) + return ERR_PTR(err); + + auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, + CRYPTO_ALG_TYPE_HASH_MASK); + if (IS_ERR(auth)) + return ERR_PTR(PTR_ERR(auth)); + + err = crypto_attr_u32(tb[2], &authsize); + inst = ERR_PTR(err); + if (err) + goto out_put_auth; + + enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER, + CRYPTO_ALG_TYPE_MASK); + inst = ERR_PTR(PTR_ERR(enc)); + if (IS_ERR(enc)) + goto out_put_auth; + + err = crypto_attr_u32(tb[4], &enckeylen); + if (err) + goto out_put_enc; + + inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); + err = -ENOMEM; + if (!inst) + goto out_put_enc; + + err = -ENAMETOOLONG; + if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, + "authenc(%s, %u, %s, %u)", auth->cra_name, authsize, + enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) + goto err_free_inst; + + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, + "authenc(%s, %u, %s, %u)", auth->cra_driver_name, + authsize, enc->cra_driver_name, enckeylen) >= + CRYPTO_MAX_ALG_NAME) + goto err_free_inst; + + ctx = crypto_instance_ctx(inst); + ctx->authsize = authsize; + ctx->enckeylen = enckeylen; + + err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); + if (err) + goto err_free_inst; + + err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK); + if (err) + goto err_drop_auth; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; + inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; + inst->alg.cra_blocksize = enc->cra_blocksize; + inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask); + inst->alg.cra_type = &crypto_aead_type; + + inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize; + inst->alg.cra_aead.authsize = authsize; + + inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); + + inst->alg.cra_init = crypto_authenc_init_tfm; + inst->alg.cra_exit = crypto_authenc_exit_tfm; + + inst->alg.cra_aead.setkey = crypto_authenc_setkey; + inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; + inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; + +out: + crypto_mod_put(enc); +out_put_auth: + crypto_mod_put(auth); + return inst; + +err_drop_auth: + crypto_drop_spawn(&ctx->auth); +err_free_inst: + kfree(inst); +out_put_enc: + inst = ERR_PTR(err); + goto out; +} + +static void crypto_authenc_free(struct crypto_instance *inst) +{ + struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); + + crypto_drop_spawn(&ctx->enc); + crypto_drop_spawn(&ctx->auth); + kfree(inst); +} + +static struct crypto_template crypto_authenc_tmpl = { + .name = "authenc", + .alloc = crypto_authenc_alloc, + .free = crypto_authenc_free, + .module = THIS_MODULE, +}; + +static int __init crypto_authenc_module_init(void) +{ + return crypto_register_template(&crypto_authenc_tmpl); +} + +static void __exit crypto_authenc_module_exit(void) +{ + crypto_unregister_template(&crypto_authenc_tmpl); +} + +module_init(crypto_authenc_module_init); +module_exit(crypto_authenc_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index cd721a7ce78..4af72dc2120 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -112,7 +112,8 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb); int crypto_check_attr_type(struct rtattr **tb, u32 type); -struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask); +struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask); +int crypto_attr_u32(struct rtattr *rta, u32 *num); struct crypto_instance *crypto_alloc_instance(const char *name, struct crypto_alg *alg); @@ -171,6 +172,26 @@ static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm) return &crypto_aead_tfm(tfm)->__crt_alg->cra_aead; } +static inline void *crypto_aead_ctx(struct crypto_aead *tfm) +{ + return crypto_tfm_ctx(&tfm->base); +} + +static inline struct crypto_instance *crypto_aead_alg_instance( + struct crypto_aead *aead) +{ + return crypto_tfm_alg_instance(&aead->base); +} + +static inline struct crypto_ablkcipher *crypto_spawn_ablkcipher( + struct crypto_spawn *spawn) +{ + u32 type = CRYPTO_ALG_TYPE_BLKCIPHER; + u32 mask = CRYPTO_ALG_TYPE_MASK; + + return __crypto_ablkcipher_cast(crypto_spawn_tfm(spawn, type, mask)); +} + static inline struct crypto_blkcipher *crypto_spawn_blkcipher( struct crypto_spawn *spawn) { @@ -257,5 +278,26 @@ static inline int ablkcipher_tfm_in_queue(struct crypto_queue *queue, return crypto_tfm_in_queue(queue, crypto_ablkcipher_tfm(tfm)); } +static inline void *aead_request_ctx(struct aead_request *req) +{ + return req->__ctx; +} + +static inline void aead_request_complete(struct aead_request *req, int err) +{ + req->base.complete(&req->base, err); +} + +static inline u32 aead_request_flags(struct aead_request *req) +{ + return req->base.flags; +} + +static inline struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, + u32 type, u32 mask) +{ + return crypto_attr_alg(tb[1], type, mask); +} + #endif /* _CRYPTO_ALGAPI_H */ -- cgit v1.2.3-70-g09d2 From 70613783fc0f6e37b442d79e8417f71a2b71ed93 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 29 Sep 2007 21:24:23 +0800 Subject: [CRYPTO] blkcipher: Remove alignment restriction on block size Previously we assumed for convenience that the block size is a multiple of the algorithm's required alignment. With the pending addition of CTR this will no longer be the case as the block size will be 1 due to it being a stream cipher. However, the alignment requirement will be that of the underlying implementation which will most likely be greater than 1. Signed-off-by: Herbert Xu --- crypto/algapi.c | 3 --- crypto/blkcipher.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'crypto/algapi.c') diff --git a/crypto/algapi.c b/crypto/algapi.c index d891f56f0e8..58cc1916480 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -63,9 +63,6 @@ static int crypto_check_alg(struct crypto_alg *alg) if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; - if (alg->cra_alignmask & alg->cra_blocksize) - return -EINVAL; - if (alg->cra_blocksize > PAGE_SIZE / 8) return -EINVAL; diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 9c49770837c..a3c87da23f1 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -149,6 +149,7 @@ static inline int blkcipher_next_slow(struct blkcipher_desc *desc, unsigned int alignmask) { unsigned int n; + unsigned aligned_bsize = ALIGN(bsize, alignmask + 1); if (walk->buffer) goto ok; @@ -167,8 +168,8 @@ ok: walk->dst.virt.addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); walk->dst.virt.addr = blkcipher_get_spot(walk->dst.virt.addr, bsize); - walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr + bsize, - bsize); + walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr + + aligned_bsize, bsize); scatterwalk_copychunks(walk->src.virt.addr, &walk->in, bsize, 0); @@ -278,7 +279,9 @@ static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, { unsigned bs = crypto_blkcipher_blocksize(tfm); unsigned int ivsize = crypto_blkcipher_ivsize(tfm); - unsigned int size = bs * 2 + ivsize + max(bs, ivsize) - (alignmask + 1); + unsigned aligned_bs = ALIGN(bs, alignmask + 1); + unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) - + (alignmask + 1); u8 *iv; size += alignmask & ~(crypto_tfm_ctx_alignment() - 1); @@ -287,8 +290,8 @@ static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, return -ENOMEM; iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); - iv = blkcipher_get_spot(iv, bs) + bs; - iv = blkcipher_get_spot(iv, bs) + bs; + iv = blkcipher_get_spot(iv, bs) + aligned_bs; + iv = blkcipher_get_spot(iv, bs) + aligned_bs; iv = blkcipher_get_spot(iv, ivsize); walk->iv = memcpy(iv, walk->iv, ivsize); -- cgit v1.2.3-70-g09d2 From d8058480b35dbc3d1e6085b3f13b80af27def09e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 2 Oct 2007 22:27:29 +0800 Subject: [CRYPTO] api: Explain the comparison on larval cra_name This patch adds a comment to explain why we compare the cra_driver_name of the algorithm being registered against the cra_name of a larval as opposed to the cra_driver_name of the larval. In fact larvals have only one name, cra_name which is the name that was requested by the user. The test here is simply trying to find out whether the algorithm being registered can or can not satisfy the larval. Signed-off-by: Herbert Xu --- crypto/algapi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'crypto/algapi.c') diff --git a/crypto/algapi.c b/crypto/algapi.c index 58cc1916480..8ff8c2656d9 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -149,6 +149,11 @@ static int __crypto_register_alg(struct crypto_alg *alg, if (crypto_is_larval(q)) { struct crypto_larval *larval = (void *)q; + /* + * Check to see if either our generic name or + * specific name can satisfy the name requested + * by the larval entry q. + */ if (strcmp(alg->cra_name, q->cra_name) && strcmp(alg->cra_driver_name, q->cra_name)) continue; -- cgit v1.2.3-70-g09d2