diff options
-rw-r--r-- | crypto/gcm.c | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/crypto/gcm.c b/crypto/gcm.c index 7d32d4720564..0c9e33bdce1a 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -38,6 +38,12 @@ struct crypto_rfc4106_ctx { u8 nonce[4]; }; +struct crypto_rfc4106_req_ctx { + struct scatterlist src[3]; + struct scatterlist dst[3]; + struct aead_request subreq; +}; + struct crypto_rfc4543_instance_ctx { struct crypto_aead_spawn aead; }; @@ -601,6 +607,15 @@ static void crypto_gcm_exit_tfm(struct crypto_aead *tfm) crypto_free_ablkcipher(ctx->ctr); } +static void crypto_gcm_free(struct aead_instance *inst) +{ + struct gcm_instance_ctx *ctx = aead_instance_ctx(inst); + + crypto_drop_skcipher(&ctx->ctr); + crypto_drop_ahash(&ctx->ghash); + kfree(inst); +} + static int crypto_gcm_create_common(struct crypto_template *tmpl, struct rtattr **tb, const char *full_name, @@ -619,7 +634,8 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, if (IS_ERR(algt)) return PTR_ERR(algt); - if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) + if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_AEAD_NEW)) & + algt->mask) return -EINVAL; ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type, @@ -674,6 +690,7 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, inst->alg.base.cra_flags = (ghash->base.cra_flags | ctr->cra_flags) & CRYPTO_ALG_ASYNC; + inst->alg.base.cra_flags |= CRYPTO_ALG_AEAD_NEW; inst->alg.base.cra_priority = (ghash->base.cra_priority + ctr->cra_priority) / 2; inst->alg.base.cra_blocksize = 1; @@ -689,6 +706,8 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, inst->alg.encrypt = crypto_gcm_encrypt; inst->alg.decrypt = crypto_gcm_decrypt; + inst->free = crypto_gcm_free; + err = aead_register_instance(tmpl, inst); if (err) goto out_put_ctr; @@ -728,19 +747,9 @@ static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb) ctr_name, "ghash"); } -static void crypto_gcm_free(struct crypto_instance *inst) -{ - struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst); - - crypto_drop_skcipher(&ctx->ctr); - crypto_drop_ahash(&ctx->ghash); - kfree(aead_instance(inst)); -} - static struct crypto_template crypto_gcm_tmpl = { .name = "gcm", .create = crypto_gcm_create, - .free = crypto_gcm_free, .module = THIS_MODULE, }; @@ -770,7 +779,6 @@ static int crypto_gcm_base_create(struct crypto_template *tmpl, static struct crypto_template crypto_gcm_base_tmpl = { .name = "gcm_base", .create = crypto_gcm_base_create, - .free = crypto_gcm_free, .module = THIS_MODULE, }; @@ -816,27 +824,50 @@ static int crypto_rfc4106_setauthsize(struct crypto_aead *parent, static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req) { - struct aead_request *subreq = aead_request_ctx(req); + struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req); struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead); + struct aead_request *subreq = &rctx->subreq; struct crypto_aead *child = ctx->child; + struct scatterlist *sg; u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child), crypto_aead_alignmask(child) + 1); + scatterwalk_map_and_copy(iv + 12, req->src, 0, req->assoclen - 8, 0); + memcpy(iv, ctx->nonce, 4); memcpy(iv + 4, req->iv, 8); + sg_init_table(rctx->src, 3); + sg_set_buf(rctx->src, iv + 12, req->assoclen - 8); + sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen); + if (sg != rctx->src + 1) + sg_chain(rctx->src, 2, sg); + + if (req->src != req->dst) { + sg_init_table(rctx->dst, 3); + sg_set_buf(rctx->dst, iv + 12, req->assoclen - 8); + sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen); + if (sg != rctx->dst + 1) + sg_chain(rctx->dst, 2, sg); + } + aead_request_set_tfm(subreq, child); aead_request_set_callback(subreq, req->base.flags, req->base.complete, req->base.data); - aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv); - aead_request_set_ad(subreq, req->assoclen); + aead_request_set_crypt(subreq, rctx->src, + req->src == req->dst ? rctx->src : rctx->dst, + req->cryptlen, iv); + aead_request_set_ad(subreq, req->assoclen - 8); return subreq; } static int crypto_rfc4106_encrypt(struct aead_request *req) { + if (req->assoclen != 16 && req->assoclen != 20) + return -EINVAL; + req = crypto_rfc4106_crypt(req); return crypto_aead_encrypt(req); @@ -844,6 +875,9 @@ static int crypto_rfc4106_encrypt(struct aead_request *req) static int crypto_rfc4106_decrypt(struct aead_request *req) { + if (req->assoclen != 16 && req->assoclen != 20) + return -EINVAL; + req = crypto_rfc4106_crypt(req); return crypto_aead_decrypt(req); @@ -867,9 +901,9 @@ static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm) align &= ~(crypto_tfm_ctx_alignment() - 1); crypto_aead_set_reqsize( tfm, - sizeof(struct aead_request) + + sizeof(struct crypto_rfc4106_req_ctx) + ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) + - align + 12); + align + 24); return 0; } @@ -881,6 +915,12 @@ static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm) crypto_free_aead(ctx->child); } +static void crypto_rfc4106_free(struct aead_instance *inst) +{ + crypto_drop_aead(aead_instance_ctx(inst)); + kfree(inst); +} + static int crypto_rfc4106_create(struct crypto_template *tmpl, struct rtattr **tb) { @@ -895,7 +935,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, if (IS_ERR(algt)) return PTR_ERR(algt); - if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) + if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_AEAD_NEW)) & + algt->mask) return -EINVAL; ccm_name = crypto_attr_alg_name(tb[1]); @@ -934,7 +975,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, CRYPTO_MAX_ALG_NAME) goto out_drop_alg; - inst->alg.base.cra_flags |= alg->base.cra_flags & CRYPTO_ALG_ASYNC; + inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; + inst->alg.base.cra_flags |= CRYPTO_ALG_AEAD_NEW; inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = alg->base.cra_alignmask; @@ -952,6 +994,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, inst->alg.encrypt = crypto_rfc4106_encrypt; inst->alg.decrypt = crypto_rfc4106_decrypt; + inst->free = crypto_rfc4106_free; + err = aead_register_instance(tmpl, inst); if (err) goto out_drop_alg; @@ -966,16 +1010,9 @@ out_free_inst: goto out; } -static void crypto_rfc4106_free(struct crypto_instance *inst) -{ - crypto_drop_aead(crypto_instance_ctx(inst)); - kfree(aead_instance(inst)); -} - static struct crypto_template crypto_rfc4106_tmpl = { .name = "rfc4106", .create = crypto_rfc4106_create, - .free = crypto_rfc4106_free, .module = THIS_MODULE, }; @@ -1114,6 +1151,15 @@ static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm) crypto_put_default_null_skcipher(); } +static void crypto_rfc4543_free(struct aead_instance *inst) +{ + struct crypto_rfc4543_instance_ctx *ctx = aead_instance_ctx(inst); + + crypto_drop_aead(&ctx->aead); + + kfree(inst); +} + static int crypto_rfc4543_create(struct crypto_template *tmpl, struct rtattr **tb) { @@ -1129,7 +1175,8 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, if (IS_ERR(algt)) return PTR_ERR(algt); - if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) + if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_AEAD_NEW)) & + algt->mask) return -EINVAL; ccm_name = crypto_attr_alg_name(tb[1]); @@ -1170,6 +1217,7 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, goto out_drop_alg; inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; + inst->alg.base.cra_flags |= CRYPTO_ALG_AEAD_NEW; inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = alg->base.cra_alignmask; @@ -1187,6 +1235,8 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, inst->alg.encrypt = crypto_rfc4543_encrypt; inst->alg.decrypt = crypto_rfc4543_decrypt; + inst->free = crypto_rfc4543_free, + err = aead_register_instance(tmpl, inst); if (err) goto out_drop_alg; @@ -1201,19 +1251,9 @@ out_free_inst: goto out; } -static void crypto_rfc4543_free(struct crypto_instance *inst) -{ - struct crypto_rfc4543_instance_ctx *ctx = crypto_instance_ctx(inst); - - crypto_drop_aead(&ctx->aead); - - kfree(aead_instance(inst)); -} - static struct crypto_template crypto_rfc4543_tmpl = { .name = "rfc4543", .create = crypto_rfc4543_create, - .free = crypto_rfc4543_free, .module = THIS_MODULE, }; |