Use the new setkey interface for poly1305 instead of supplying the key via the first two blocks. In order to do this, clone the shash transform for each request. Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> --- crypto/chacha20poly1305.c | 115 ++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 48 deletions(-) diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index d740849f1c19..cd8e3b5c55b5 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -51,6 +51,8 @@ struct chacha_req { struct chachapoly_req_ctx { struct scatterlist src[2]; struct scatterlist dst[2]; + /* Poly1305 transform with generated key */ + struct crypto_ahash *poly; /* the key we generate for Poly1305 using Chacha20 */ u8 key[POLY1305_KEY_SIZE]; /* calculated Poly1305 tag */ @@ -81,6 +83,26 @@ static inline void async_done_continue(struct aead_request *req, int err, aead_request_complete(req, err); } +static inline void poly_done_continue(struct aead_request *req, int err, + int (*cont)(struct aead_request *)) +{ + if (err && err != -EINPROGRESS && err != -EBUSY) { + struct chachapoly_req_ctx *rctx = aead_request_ctx(req); + + crypto_free_ahash(rctx->poly); + } + async_done_continue(req, err, cont); +} + +static int poly_check_err(struct aead_request *req, int err) +{ + struct chachapoly_req_ctx *rctx = aead_request_ctx(req); + + if (err && err != -EINPROGRESS && err != -EBUSY) + crypto_free_ahash(rctx->poly); + return err; +} + static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb) { struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); @@ -155,6 +177,8 @@ static int poly_tail_continue(struct aead_request *req) { struct chachapoly_req_ctx *rctx = aead_request_ctx(req); + crypto_free_ahash(rctx->poly); + if (rctx->cryptlen == req->cryptlen) /* encrypting */ return poly_copy_tag(req); @@ -163,13 +187,11 @@ static int poly_tail_continue(struct aead_request *req) static void poly_tail_done(void *data, int err) { - async_done_continue(data, err, poly_tail_continue); + poly_done_continue(data, err, poly_tail_continue); } static int poly_tail(struct aead_request *req) { - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; int err; @@ -180,11 +202,12 @@ static int poly_tail(struct aead_request *req) ahash_request_set_callback(&preq->req, rctx->flags, poly_tail_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); ahash_request_set_crypt(&preq->req, preq->src, rctx->tag, sizeof(preq->tail)); err = crypto_ahash_finup(&preq->req); + err = poly_check_err(req, err); if (err) return err; @@ -193,12 +216,11 @@ static int poly_tail(struct aead_request *req) static void poly_cipherpad_done(void *data, int err) { - async_done_continue(data, err, poly_tail); + poly_done_continue(data, err, poly_tail); } static int poly_cipherpad(struct aead_request *req) { - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; unsigned int padlen; @@ -210,10 +232,11 @@ static int poly_cipherpad(struct aead_request *req) ahash_request_set_callback(&preq->req, rctx->flags, poly_cipherpad_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); err = crypto_ahash_update(&preq->req); + err = poly_check_err(req, err); if (err) return err; @@ -222,12 +245,11 @@ static int poly_cipherpad(struct aead_request *req) static void poly_cipher_done(void *data, int err) { - async_done_continue(data, err, poly_cipherpad); + poly_done_continue(data, err, poly_cipherpad); } static int poly_cipher(struct aead_request *req) { - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; struct scatterlist *crypt = req->src; @@ -240,10 +262,11 @@ static int poly_cipher(struct aead_request *req) ahash_request_set_callback(&preq->req, rctx->flags, poly_cipher_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); err = crypto_ahash_update(&preq->req); + err = poly_check_err(req, err); if (err) return err; @@ -252,12 +275,11 @@ static int poly_cipher(struct aead_request *req) static void poly_adpad_done(void *data, int err) { - async_done_continue(data, err, poly_cipher); + poly_done_continue(data, err, poly_cipher); } static int poly_adpad(struct aead_request *req) { - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; unsigned int padlen; @@ -269,10 +291,11 @@ static int poly_adpad(struct aead_request *req) ahash_request_set_callback(&preq->req, rctx->flags, poly_adpad_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); err = crypto_ahash_update(&preq->req); + err = poly_check_err(req, err); if (err) return err; @@ -281,80 +304,76 @@ static int poly_adpad(struct aead_request *req) static void poly_ad_done(void *data, int err) { - async_done_continue(data, err, poly_adpad); + poly_done_continue(data, err, poly_adpad); } static int poly_ad(struct aead_request *req) { - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; int err; ahash_request_set_callback(&preq->req, rctx->flags, poly_ad_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); err = crypto_ahash_update(&preq->req); + err = poly_check_err(req, err); if (err) return err; return poly_adpad(req); } -static void poly_setkey_done(void *data, int err) -{ - async_done_continue(data, err, poly_ad); -} - -static int poly_setkey(struct aead_request *req) -{ - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); - struct chachapoly_req_ctx *rctx = aead_request_ctx(req); - struct poly_req *preq = &rctx->u.poly; - int err; - - sg_init_one(preq->src, rctx->key, sizeof(rctx->key)); - - ahash_request_set_callback(&preq->req, rctx->flags, - poly_setkey_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); - ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); - - err = crypto_ahash_update(&preq->req); - if (err) - return err; - - return poly_ad(req); -} - static void poly_init_done(void *data, int err) { - async_done_continue(data, err, poly_setkey); + poly_done_continue(data, err, poly_ad); } static int poly_init(struct aead_request *req) { - struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct chachapoly_req_ctx *rctx = aead_request_ctx(req); struct poly_req *preq = &rctx->u.poly; int err; ahash_request_set_callback(&preq->req, rctx->flags, poly_init_done, req); - ahash_request_set_tfm(&preq->req, ctx->poly); + ahash_request_set_tfm(&preq->req, rctx->poly); err = crypto_ahash_init(&preq->req); + err = poly_check_err(req, err); if (err) return err; - return poly_setkey(req); + return poly_ad(req); +} + +static int poly_setkey(struct aead_request *req) +{ + struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); + struct chachapoly_req_ctx *rctx = aead_request_ctx(req); + struct crypto_ahash *poly; + int err; + + poly = crypto_clone_ahash(ctx->poly); + if (IS_ERR(poly)) + return PTR_ERR(poly); + + err = crypto_ahash_setkey(poly, rctx->key, sizeof(rctx->key)); + if (err) { + crypto_free_ahash(poly); + return err; + } + + rctx->poly = poly; + + return poly_init(req); } static void poly_genkey_done(void *data, int err) { - async_done_continue(data, err, poly_init); + async_done_continue(data, err, poly_setkey); } static int poly_genkey(struct aead_request *req) @@ -388,7 +407,7 @@ static int poly_genkey(struct aead_request *req) if (err) return err; - return poly_init(req); + return poly_setkey(req); } static void chacha_encrypt_done(void *data, int err) -- 2.39.5