From c2b7b20aedfa10de3634877c3e4b7bc9a7d6461e Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 16 Jun 2015 11:34:16 +0200 Subject: crypto: poly1305 - Pass key as first two message blocks to each desc_ctx The Poly1305 authenticator requires a unique key for each generated tag. This implies that we can't set the key per tfm, as multiple users set individual keys. Instead we pass a desc specific key as the first two blocks of the message to authenticate in update(). Signed-off-by: Martin Willi Signed-off-by: Herbert Xu --- crypto/chacha20poly1305.c | 54 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 23 deletions(-) (limited to 'crypto/chacha20poly1305.c') diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index 05fbc59297e5..7b46ed799a64 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -54,14 +54,14 @@ struct poly_req { }; struct chacha_req { - /* the key we generate for Poly1305 using Chacha20 */ - u8 key[POLY1305_KEY_SIZE]; u8 iv[CHACHA20_IV_SIZE]; struct scatterlist src[1]; struct ablkcipher_request req; /* must be last member */ }; struct chachapoly_req_ctx { + /* the key we generate for Poly1305 using Chacha20 */ + u8 key[POLY1305_KEY_SIZE]; /* calculated Poly1305 tag */ u8 tag[POLY1305_DIGEST_SIZE]; /* length of data to en/decrypt, without ICV */ @@ -294,53 +294,59 @@ static int poly_ad(struct aead_request *req) return poly_adpad(req); } -static void poly_init_done(struct crypto_async_request *areq, int err) +static void poly_setkey_done(struct crypto_async_request *areq, int err) { async_done_continue(areq->data, err, poly_ad); } -static int poly_init(struct aead_request *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 poly_req *preq = &rctx->u.poly; int err; + sg_init_table(preq->src, 1); + sg_set_buf(preq->src, rctx->key, sizeof(rctx->key)); + ahash_request_set_callback(&preq->req, aead_request_flags(req), - poly_init_done, req); + 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_init(&preq->req); + err = crypto_ahash_update(&preq->req); if (err) return err; return poly_ad(req); } -static int poly_genkey_continue(struct aead_request *req) +static void poly_init_done(struct crypto_async_request *areq, int err) { - struct crypto_aead *aead = crypto_aead_reqtfm(req); - struct chachapoly_ctx *ctx = crypto_aead_ctx(aead); + async_done_continue(areq->data, err, poly_setkey); +} + +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 chacha_req *creq = &rctx->u.chacha; + struct poly_req *preq = &rctx->u.poly; int err; - crypto_ahash_clear_flags(ctx->poly, CRYPTO_TFM_REQ_MASK); - crypto_ahash_set_flags(ctx->poly, crypto_aead_get_flags(aead) & - CRYPTO_TFM_REQ_MASK); + ahash_request_set_callback(&preq->req, aead_request_flags(req), + poly_init_done, req); + ahash_request_set_tfm(&preq->req, ctx->poly); - err = crypto_ahash_setkey(ctx->poly, creq->key, sizeof(creq->key)); - crypto_aead_set_flags(aead, crypto_ahash_get_flags(ctx->poly) & - CRYPTO_TFM_RES_MASK); + err = crypto_ahash_init(&preq->req); if (err) return err; - return poly_init(req); + return poly_setkey(req); } static void poly_genkey_done(struct crypto_async_request *areq, int err) { - async_done_continue(areq->data, err, poly_genkey_continue); + async_done_continue(areq->data, err, poly_init); } static int poly_genkey(struct aead_request *req) @@ -351,8 +357,8 @@ static int poly_genkey(struct aead_request *req) int err; sg_init_table(creq->src, 1); - memset(creq->key, 0, sizeof(creq->key)); - sg_set_buf(creq->src, creq->key, sizeof(creq->key)); + memset(rctx->key, 0, sizeof(rctx->key)); + sg_set_buf(creq->src, rctx->key, sizeof(rctx->key)); chacha_iv(creq->iv, req, 0); @@ -366,7 +372,7 @@ static int poly_genkey(struct aead_request *req) if (err) return err; - return poly_genkey_continue(req); + return poly_init(req); } static void chacha_encrypt_done(struct crypto_async_request *areq, int err) @@ -403,8 +409,9 @@ static int chachapoly_encrypt(struct aead_request *req) /* encrypt call chain: * - chacha_encrypt/done() - * - poly_genkey/done/continue() + * - poly_genkey/done() * - poly_init/done() + * - poly_setkey/done() * - poly_ad/done() * - poly_adpad/done() * - poly_cipher/done() @@ -424,8 +431,9 @@ static int chachapoly_decrypt(struct aead_request *req) rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; /* decrypt call chain: - * - poly_genkey/done/continue() + * - poly_genkey/done() * - poly_init/done() + * - poly_setkey/done() * - poly_ad/done() * - poly_adpad/done() * - poly_cipher/done() -- cgit v1.2.3