Skip to content

Commit

Permalink
crypto: gcm - Use new IV convention
Browse files Browse the repository at this point in the history
This patch converts rfc4106 to the new calling convention where
the IV is now part of the AD and needs to be skipped.  This patch
also makes use of the new type-safe way of freeing instances.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
herbertx committed Jul 14, 2015
1 parent e9b8d2c commit 7b05a37
Showing 1 changed file with 77 additions and 37 deletions.
114 changes: 77 additions & 37 deletions crypto/gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
};

Expand Down Expand Up @@ -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,
};

Expand Down Expand Up @@ -816,34 +824,60 @@ 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);
}

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);
Expand All @@ -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;
}
Expand All @@ -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)
{
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -966,16 +1010,9 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl,
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,
};

Expand Down Expand Up @@ -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)
{
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -1201,19 +1251,9 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl,
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,
};

Expand Down

0 comments on commit 7b05a37

Please sign in to comment.