diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-05-27 05:24:41 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-05-27 23:23:21 -0400 |
commit | 19fa77522e45e384be0f0f93b10c928763460ae3 (patch) | |
tree | 55c94d34e0e61b480801a0eb7c41d9764c6b9245 /crypto/algif_aead.c | |
parent | a3f2185a29df084611641e964aa93d1a6ee2212c (diff) |
crypto: algif_aead - Switch to new AEAD interface
This patch makes use of the new AEAD interface which uses a single
SG list instead of separate lists for the AD and plain text.
Note that the user-space interface now requires both input and
output to be of the same length, and both must include space for
the AD as well as the authentication tag.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/algif_aead.c')
-rw-r--r-- | crypto/algif_aead.c | 66 |
1 files changed, 8 insertions, 58 deletions
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index a55e4e6fa3d8..38a6cab7aeca 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c | |||
@@ -72,7 +72,7 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx) | |||
72 | { | 72 | { |
73 | unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); | 73 | unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); |
74 | 74 | ||
75 | return (ctx->used >= (ctx->aead_assoclen + (ctx->enc ? 0 : as))); | 75 | return ctx->used >= ctx->aead_assoclen + as; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void aead_put_sgl(struct sock *sk) | 78 | static void aead_put_sgl(struct sock *sk) |
@@ -353,12 +353,8 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | |||
353 | struct sock *sk = sock->sk; | 353 | struct sock *sk = sock->sk; |
354 | struct alg_sock *ask = alg_sk(sk); | 354 | struct alg_sock *ask = alg_sk(sk); |
355 | struct aead_ctx *ctx = ask->private; | 355 | struct aead_ctx *ctx = ask->private; |
356 | unsigned bs = crypto_aead_blocksize(crypto_aead_reqtfm(&ctx->aead_req)); | ||
357 | unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); | 356 | unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); |
358 | struct aead_sg_list *sgl = &ctx->tsgl; | 357 | struct aead_sg_list *sgl = &ctx->tsgl; |
359 | struct scatterlist *sg = NULL; | ||
360 | struct scatterlist assoc[ALG_MAX_PAGES]; | ||
361 | size_t assoclen = 0; | ||
362 | unsigned int i = 0; | 358 | unsigned int i = 0; |
363 | int err = -EINVAL; | 359 | int err = -EINVAL; |
364 | unsigned long used = 0; | 360 | unsigned long used = 0; |
@@ -407,23 +403,13 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | |||
407 | if (!aead_sufficient_data(ctx)) | 403 | if (!aead_sufficient_data(ctx)) |
408 | goto unlock; | 404 | goto unlock; |
409 | 405 | ||
406 | outlen = used; | ||
407 | |||
410 | /* | 408 | /* |
411 | * The cipher operation input data is reduced by the associated data | 409 | * The cipher operation input data is reduced by the associated data |
412 | * length as this data is processed separately later on. | 410 | * length as this data is processed separately later on. |
413 | */ | 411 | */ |
414 | used -= ctx->aead_assoclen; | 412 | used -= ctx->aead_assoclen + (ctx->enc ? as : 0); |
415 | |||
416 | if (ctx->enc) { | ||
417 | /* round up output buffer to multiple of block size */ | ||
418 | outlen = ((used + bs - 1) / bs * bs); | ||
419 | /* add the size needed for the auth tag to be created */ | ||
420 | outlen += as; | ||
421 | } else { | ||
422 | /* output data size is input without the authentication tag */ | ||
423 | outlen = used - as; | ||
424 | /* round up output buffer to multiple of block size */ | ||
425 | outlen = ((outlen + bs - 1) / bs * bs); | ||
426 | } | ||
427 | 413 | ||
428 | /* convert iovecs of output buffers into scatterlists */ | 414 | /* convert iovecs of output buffers into scatterlists */ |
429 | while (iov_iter_count(&msg->msg_iter)) { | 415 | while (iov_iter_count(&msg->msg_iter)) { |
@@ -452,47 +438,11 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | |||
452 | if (usedpages < outlen) | 438 | if (usedpages < outlen) |
453 | goto unlock; | 439 | goto unlock; |
454 | 440 | ||
455 | sg_init_table(assoc, ALG_MAX_PAGES); | 441 | sg_mark_end(sgl->sg + sgl->cur - 1); |
456 | assoclen = ctx->aead_assoclen; | ||
457 | /* | ||
458 | * Split scatterlist into two: first part becomes AD, second part | ||
459 | * is plaintext / ciphertext. The first part is assigned to assoc | ||
460 | * scatterlist. When this loop finishes, sg points to the start of the | ||
461 | * plaintext / ciphertext. | ||
462 | */ | ||
463 | for (i = 0; i < ctx->tsgl.cur; i++) { | ||
464 | sg = sgl->sg + i; | ||
465 | if (sg->length <= assoclen) { | ||
466 | /* AD is larger than one page */ | ||
467 | sg_set_page(assoc + i, sg_page(sg), | ||
468 | sg->length, sg->offset); | ||
469 | assoclen -= sg->length; | ||
470 | if (i >= ctx->tsgl.cur) | ||
471 | goto unlock; | ||
472 | } else if (!assoclen) { | ||
473 | /* current page is to start of plaintext / ciphertext */ | ||
474 | if (i) | ||
475 | /* AD terminates at page boundary */ | ||
476 | sg_mark_end(assoc + i - 1); | ||
477 | else | ||
478 | /* AD size is zero */ | ||
479 | sg_mark_end(assoc); | ||
480 | break; | ||
481 | } else { | ||
482 | /* AD does not terminate at page boundary */ | ||
483 | sg_set_page(assoc + i, sg_page(sg), | ||
484 | assoclen, sg->offset); | ||
485 | sg_mark_end(assoc + i); | ||
486 | /* plaintext / ciphertext starts after AD */ | ||
487 | sg->length -= assoclen; | ||
488 | sg->offset += assoclen; | ||
489 | break; | ||
490 | } | ||
491 | } | ||
492 | 442 | ||
493 | aead_request_set_assoc(&ctx->aead_req, assoc, ctx->aead_assoclen); | 443 | aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg, |
494 | aead_request_set_crypt(&ctx->aead_req, sg, ctx->rsgl[0].sg, used, | 444 | used, ctx->iv); |
495 | ctx->iv); | 445 | aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen); |
496 | 446 | ||
497 | err = af_alg_wait_for_completion(ctx->enc ? | 447 | err = af_alg_wait_for_completion(ctx->enc ? |
498 | crypto_aead_encrypt(&ctx->aead_req) : | 448 | crypto_aead_encrypt(&ctx->aead_req) : |