diff options
Diffstat (limited to 'crypto/authenc.c')
-rw-r--r-- | crypto/authenc.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c index ffce19de05cf..e1223559d5df 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c | |||
@@ -52,40 +52,52 @@ static void authenc_request_complete(struct aead_request *req, int err) | |||
52 | aead_request_complete(req, err); | 52 | aead_request_complete(req, err); |
53 | } | 53 | } |
54 | 54 | ||
55 | static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, | 55 | int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key, |
56 | unsigned int keylen) | 56 | unsigned int keylen) |
57 | { | 57 | { |
58 | unsigned int authkeylen; | 58 | struct rtattr *rta = (struct rtattr *)key; |
59 | unsigned int enckeylen; | ||
60 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | ||
61 | struct crypto_ahash *auth = ctx->auth; | ||
62 | struct crypto_ablkcipher *enc = ctx->enc; | ||
63 | struct rtattr *rta = (void *)key; | ||
64 | struct crypto_authenc_key_param *param; | 59 | struct crypto_authenc_key_param *param; |
65 | int err = -EINVAL; | ||
66 | 60 | ||
67 | if (!RTA_OK(rta, keylen)) | 61 | if (!RTA_OK(rta, keylen)) |
68 | goto badkey; | 62 | return -EINVAL; |
69 | if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) | 63 | if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) |
70 | goto badkey; | 64 | return -EINVAL; |
71 | if (RTA_PAYLOAD(rta) < sizeof(*param)) | 65 | if (RTA_PAYLOAD(rta) < sizeof(*param)) |
72 | goto badkey; | 66 | return -EINVAL; |
73 | 67 | ||
74 | param = RTA_DATA(rta); | 68 | param = RTA_DATA(rta); |
75 | enckeylen = be32_to_cpu(param->enckeylen); | 69 | keys->enckeylen = be32_to_cpu(param->enckeylen); |
76 | 70 | ||
77 | key += RTA_ALIGN(rta->rta_len); | 71 | key += RTA_ALIGN(rta->rta_len); |
78 | keylen -= RTA_ALIGN(rta->rta_len); | 72 | keylen -= RTA_ALIGN(rta->rta_len); |
79 | 73 | ||
80 | if (keylen < enckeylen) | 74 | if (keylen < keys->enckeylen) |
81 | goto badkey; | 75 | return -EINVAL; |
82 | 76 | ||
83 | authkeylen = keylen - enckeylen; | 77 | keys->authkeylen = keylen - keys->enckeylen; |
78 | keys->authkey = key; | ||
79 | keys->enckey = key + keys->authkeylen; | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(crypto_authenc_extractkeys); | ||
84 | |||
85 | static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, | ||
86 | unsigned int keylen) | ||
87 | { | ||
88 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | ||
89 | struct crypto_ahash *auth = ctx->auth; | ||
90 | struct crypto_ablkcipher *enc = ctx->enc; | ||
91 | struct crypto_authenc_keys keys; | ||
92 | int err = -EINVAL; | ||
93 | |||
94 | if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) | ||
95 | goto badkey; | ||
84 | 96 | ||
85 | crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); | 97 | crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); |
86 | crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) & | 98 | crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) & |
87 | CRYPTO_TFM_REQ_MASK); | 99 | CRYPTO_TFM_REQ_MASK); |
88 | err = crypto_ahash_setkey(auth, key, authkeylen); | 100 | err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen); |
89 | crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) & | 101 | crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) & |
90 | CRYPTO_TFM_RES_MASK); | 102 | CRYPTO_TFM_RES_MASK); |
91 | 103 | ||
@@ -95,7 +107,7 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, | |||
95 | crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); | 107 | crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); |
96 | crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) & | 108 | crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) & |
97 | CRYPTO_TFM_REQ_MASK); | 109 | CRYPTO_TFM_REQ_MASK); |
98 | err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen); | 110 | err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen); |
99 | crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) & | 111 | crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) & |
100 | CRYPTO_TFM_RES_MASK); | 112 | CRYPTO_TFM_RES_MASK); |
101 | 113 | ||
@@ -188,7 +200,7 @@ static void authenc_verify_ahash_update_done(struct crypto_async_request *areq, | |||
188 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, | 200 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, |
189 | authsize, 0); | 201 | authsize, 0); |
190 | 202 | ||
191 | err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0; | 203 | err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0; |
192 | if (err) | 204 | if (err) |
193 | goto out; | 205 | goto out; |
194 | 206 | ||
@@ -227,7 +239,7 @@ static void authenc_verify_ahash_done(struct crypto_async_request *areq, | |||
227 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, | 239 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, |
228 | authsize, 0); | 240 | authsize, 0); |
229 | 241 | ||
230 | err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0; | 242 | err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0; |
231 | if (err) | 243 | if (err) |
232 | goto out; | 244 | goto out; |
233 | 245 | ||
@@ -368,9 +380,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, | |||
368 | if (!err) { | 380 | if (!err) { |
369 | struct crypto_aead *authenc = crypto_aead_reqtfm(areq); | 381 | struct crypto_aead *authenc = crypto_aead_reqtfm(areq); |
370 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 382 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
371 | struct ablkcipher_request *abreq = aead_request_ctx(areq); | 383 | struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq); |
372 | u8 *iv = (u8 *)(abreq + 1) + | 384 | struct ablkcipher_request *abreq = (void *)(areq_ctx->tail |
373 | crypto_ablkcipher_reqsize(ctx->enc); | 385 | + ctx->reqoff); |
386 | u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc); | ||
374 | 387 | ||
375 | err = crypto_authenc_genicv(areq, iv, 0); | 388 | err = crypto_authenc_genicv(areq, iv, 0); |
376 | } | 389 | } |
@@ -462,7 +475,7 @@ static int crypto_authenc_verify(struct aead_request *req, | |||
462 | ihash = ohash + authsize; | 475 | ihash = ohash + authsize; |
463 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, | 476 | scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, |
464 | authsize, 0); | 477 | authsize, 0); |
465 | return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0; | 478 | return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0; |
466 | } | 479 | } |
467 | 480 | ||
468 | static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, | 481 | static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, |