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, |
