]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - crypto/gcm.c
Merge branch 'pci/host-layerscape' into next
[karo-tx-linux.git] / crypto / gcm.c
index 7d32d4720564315f57a2766f5e1813d536d9ee69..bec329b3de8d7f2e51ed3bf2d91afcdbe4678e8d 100644 (file)
@@ -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;
 };
@@ -200,14 +206,14 @@ static void crypto_gcm_init_common(struct aead_request *req)
        sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
        sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
        if (sg != pctx->src + 1)
-               scatterwalk_sg_chain(pctx->src, 2, sg);
+               sg_chain(pctx->src, 2, sg);
 
        if (req->src != req->dst) {
                sg_init_table(pctx->dst, 3);
                sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
                sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
                if (sg != pctx->dst + 1)
-                       scatterwalk_sg_chain(pctx->dst, 2, sg);
+                       sg_chain(pctx->dst, 2, sg);
        }
 }
 
@@ -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,
@@ -689,6 +704,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 +745,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 +777,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 +822,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 +873,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 +899,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 +913,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)
 {
@@ -934,7 +972,7 @@ 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_priority = alg->base.cra_priority;
        inst->alg.base.cra_blocksize = 1;
        inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
@@ -952,6 +990,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 +1006,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 +1147,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)
 {
@@ -1187,6 +1229,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 +1245,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,
 };