summaryrefslogtreecommitdiffstats
path: root/crypto/echainiv.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-07-08 19:17:20 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-07-14 02:56:46 -0400
commit5499b1a7311f5ec301ac2baa04a3482ee89ac0ab (patch)
tree2f6ad76458338ec95a60b478b093a7c973a72be3 /crypto/echainiv.c
parentf6da32059324e06adacbc1235d50cce4de9d817a (diff)
crypto: echainiv - Fix encryption convention
This patch fixes a bug where we were incorrectly including the IV in the AD during encryption. The IV must remain in the plain text for it to be encrypted. During decryption there is no need to copy the IV to dst because it's now part of the AD. This patch removes an unncessary check on authsize which would be performed by the underlying decrypt call. Finally this patch makes use of the type-safe init/exit functions. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/echainiv.c')
-rw-r--r--crypto/echainiv.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/crypto/echainiv.c b/crypto/echainiv.c
index b6e43dc61356..d3896c7e634b 100644
--- a/crypto/echainiv.c
+++ b/crypto/echainiv.c
@@ -145,8 +145,8 @@ static int echainiv_encrypt(struct aead_request *req)
145 145
146 aead_request_set_callback(subreq, req->base.flags, compl, data); 146 aead_request_set_callback(subreq, req->base.flags, compl, data);
147 aead_request_set_crypt(subreq, req->dst, req->dst, 147 aead_request_set_crypt(subreq, req->dst, req->dst,
148 req->cryptlen - ivsize, info); 148 req->cryptlen, info);
149 aead_request_set_ad(subreq, req->assoclen + ivsize); 149 aead_request_set_ad(subreq, req->assoclen);
150 150
151 crypto_xor(info, ctx->salt, ivsize); 151 crypto_xor(info, ctx->salt, ivsize);
152 scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); 152 scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
@@ -166,7 +166,7 @@ static int echainiv_decrypt(struct aead_request *req)
166 void *data; 166 void *data;
167 unsigned int ivsize = crypto_aead_ivsize(geniv); 167 unsigned int ivsize = crypto_aead_ivsize(geniv);
168 168
169 if (req->cryptlen < ivsize + crypto_aead_authsize(geniv)) 169 if (req->cryptlen < ivsize)
170 return -EINVAL; 170 return -EINVAL;
171 171
172 aead_request_set_tfm(subreq, ctx->geniv.child); 172 aead_request_set_tfm(subreq, ctx->geniv.child);
@@ -180,16 +180,12 @@ static int echainiv_decrypt(struct aead_request *req)
180 aead_request_set_ad(subreq, req->assoclen + ivsize); 180 aead_request_set_ad(subreq, req->assoclen + ivsize);
181 181
182 scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); 182 scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
183 if (req->src != req->dst)
184 scatterwalk_map_and_copy(req->iv, req->dst,
185 req->assoclen, ivsize, 1);
186 183
187 return crypto_aead_decrypt(subreq); 184 return crypto_aead_decrypt(subreq);
188} 185}
189 186
190static int echainiv_init(struct crypto_tfm *tfm) 187static int echainiv_init(struct crypto_aead *geniv)
191{ 188{
192 struct crypto_aead *geniv = __crypto_aead_cast(tfm);
193 struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); 189 struct echainiv_ctx *ctx = crypto_aead_ctx(geniv);
194 int err; 190 int err;
195 191
@@ -212,7 +208,7 @@ static int echainiv_init(struct crypto_tfm *tfm)
212 if (IS_ERR(ctx->null)) 208 if (IS_ERR(ctx->null))
213 goto out; 209 goto out;
214 210
215 err = aead_geniv_init(tfm); 211 err = aead_geniv_init(crypto_aead_tfm(geniv));
216 if (err) 212 if (err)
217 goto drop_null; 213 goto drop_null;
218 214
@@ -227,9 +223,9 @@ drop_null:
227 goto out; 223 goto out;
228} 224}
229 225
230static void echainiv_exit(struct crypto_tfm *tfm) 226static void echainiv_exit(struct crypto_aead *tfm)
231{ 227{
232 struct echainiv_ctx *ctx = crypto_tfm_ctx(tfm); 228 struct echainiv_ctx *ctx = crypto_aead_ctx(tfm);
233 229
234 crypto_free_aead(ctx->geniv.child); 230 crypto_free_aead(ctx->geniv.child);
235 crypto_put_default_null_skcipher(); 231 crypto_put_default_null_skcipher();
@@ -262,13 +258,15 @@ static int echainiv_aead_create(struct crypto_template *tmpl,
262 inst->alg.encrypt = echainiv_encrypt; 258 inst->alg.encrypt = echainiv_encrypt;
263 inst->alg.decrypt = echainiv_decrypt; 259 inst->alg.decrypt = echainiv_decrypt;
264 260
265 inst->alg.base.cra_init = echainiv_init; 261 inst->alg.init = echainiv_init;
266 inst->alg.base.cra_exit = echainiv_exit; 262 inst->alg.exit = echainiv_exit;
267 263
268 inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; 264 inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
269 inst->alg.base.cra_ctxsize = sizeof(struct echainiv_ctx); 265 inst->alg.base.cra_ctxsize = sizeof(struct echainiv_ctx);
270 inst->alg.base.cra_ctxsize += inst->alg.ivsize; 266 inst->alg.base.cra_ctxsize += inst->alg.ivsize;
271 267
268 inst->free = aead_geniv_free;
269
272done: 270done:
273 err = aead_register_instance(tmpl, inst); 271 err = aead_register_instance(tmpl, inst);
274 if (err) 272 if (err)