diff options
Diffstat (limited to 'kernel/crypto/cryptd.c')
-rw-r--r-- | kernel/crypto/cryptd.c | 154 |
1 files changed, 92 insertions, 62 deletions
diff --git a/kernel/crypto/cryptd.c b/kernel/crypto/cryptd.c index b0602ba03..c81861b13 100644 --- a/kernel/crypto/cryptd.c +++ b/kernel/crypto/cryptd.c @@ -176,10 +176,9 @@ static inline void cryptd_check_internal(struct rtattr **tb, u32 *type, algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return; - if ((algt->type & CRYPTO_ALG_INTERNAL)) - *type |= CRYPTO_ALG_INTERNAL; - if ((algt->mask & CRYPTO_ALG_INTERNAL)) - *mask |= CRYPTO_ALG_INTERNAL; + + *type |= algt->type & CRYPTO_ALG_INTERNAL; + *mask |= algt->mask & CRYPTO_ALG_INTERNAL; } static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent, @@ -295,6 +294,23 @@ static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm) crypto_free_blkcipher(ctx->child); } +static int cryptd_init_instance(struct crypto_instance *inst, + struct crypto_alg *alg) +{ + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, + "cryptd(%s)", + alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) + return -ENAMETOOLONG; + + memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); + + inst->alg.cra_priority = alg->cra_priority + 50; + inst->alg.cra_blocksize = alg->cra_blocksize; + inst->alg.cra_alignmask = alg->cra_alignmask; + + return 0; +} + static void *cryptd_alloc_instance(struct crypto_alg *alg, unsigned int head, unsigned int tail) { @@ -308,17 +324,10 @@ static void *cryptd_alloc_instance(struct crypto_alg *alg, unsigned int head, inst = (void *)(p + head); - err = -ENAMETOOLONG; - if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, - "cryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) + err = cryptd_init_instance(inst, alg); + if (err) goto out_free_inst; - memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); - - inst->alg.cra_priority = alg->cra_priority + 50; - inst->alg.cra_blocksize = alg->cra_blocksize; - inst->alg.cra_alignmask = alg->cra_alignmask; - out: return p; @@ -654,22 +663,42 @@ out_put_alg: return err; } +static int cryptd_aead_setkey(struct crypto_aead *parent, + const u8 *key, unsigned int keylen) +{ + struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent); + struct crypto_aead *child = ctx->child; + + return crypto_aead_setkey(child, key, keylen); +} + +static int cryptd_aead_setauthsize(struct crypto_aead *parent, + unsigned int authsize) +{ + struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent); + struct crypto_aead *child = ctx->child; + + return crypto_aead_setauthsize(child, authsize); +} + static void cryptd_aead_crypt(struct aead_request *req, struct crypto_aead *child, int err, int (*crypt)(struct aead_request *req)) { struct cryptd_aead_request_ctx *rctx; + crypto_completion_t compl; + rctx = aead_request_ctx(req); + compl = rctx->complete; if (unlikely(err == -EINPROGRESS)) goto out; aead_request_set_tfm(req, child); err = crypt( req ); - req->base.complete = rctx->complete; out: local_bh_disable(); - rctx->complete(&req->base, err); + compl(&req->base, err); local_bh_enable(); } @@ -680,7 +709,7 @@ static void cryptd_aead_encrypt(struct crypto_async_request *areq, int err) struct aead_request *req; req = container_of(areq, struct aead_request, base); - cryptd_aead_crypt(req, child, err, crypto_aead_crt(child)->encrypt); + cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->encrypt); } static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err) @@ -690,7 +719,7 @@ static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err) struct aead_request *req; req = container_of(areq, struct aead_request, base); - cryptd_aead_crypt(req, child, err, crypto_aead_crt(child)->decrypt); + cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->decrypt); } static int cryptd_aead_enqueue(struct aead_request *req, @@ -715,27 +744,28 @@ static int cryptd_aead_decrypt_enqueue(struct aead_request *req) return cryptd_aead_enqueue(req, cryptd_aead_decrypt ); } -static int cryptd_aead_init_tfm(struct crypto_tfm *tfm) +static int cryptd_aead_init_tfm(struct crypto_aead *tfm) { - struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); - struct aead_instance_ctx *ictx = crypto_instance_ctx(inst); + struct aead_instance *inst = aead_alg_instance(tfm); + struct aead_instance_ctx *ictx = aead_instance_ctx(inst); struct crypto_aead_spawn *spawn = &ictx->aead_spawn; - struct cryptd_aead_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_aead *cipher; cipher = crypto_spawn_aead(spawn); if (IS_ERR(cipher)) return PTR_ERR(cipher); - crypto_aead_set_flags(cipher, CRYPTO_TFM_REQ_MAY_SLEEP); ctx->child = cipher; - tfm->crt_aead.reqsize = sizeof(struct cryptd_aead_request_ctx); + crypto_aead_set_reqsize( + tfm, max((unsigned)sizeof(struct cryptd_aead_request_ctx), + crypto_aead_reqsize(cipher))); return 0; } -static void cryptd_aead_exit_tfm(struct crypto_tfm *tfm) +static void cryptd_aead_exit_tfm(struct crypto_aead *tfm) { - struct cryptd_aead_ctx *ctx = crypto_tfm_ctx(tfm); + struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm); crypto_free_aead(ctx->child); } @@ -744,57 +774,57 @@ static int cryptd_create_aead(struct crypto_template *tmpl, struct cryptd_queue *queue) { struct aead_instance_ctx *ctx; - struct crypto_instance *inst; - struct crypto_alg *alg; - u32 type = CRYPTO_ALG_TYPE_AEAD; - u32 mask = CRYPTO_ALG_TYPE_MASK; + struct aead_instance *inst; + struct aead_alg *alg; + const char *name; + u32 type = 0; + u32 mask = CRYPTO_ALG_ASYNC; int err; cryptd_check_internal(tb, &type, &mask); - alg = crypto_get_attr_alg(tb, type, mask); - if (IS_ERR(alg)) - return PTR_ERR(alg); + name = crypto_attr_alg_name(tb[1]); + if (IS_ERR(name)) + return PTR_ERR(name); - inst = cryptd_alloc_instance(alg, 0, sizeof(*ctx)); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto out_put_alg; + inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); + if (!inst) + return -ENOMEM; - ctx = crypto_instance_ctx(inst); + ctx = aead_instance_ctx(inst); ctx->queue = queue; - err = crypto_init_spawn(&ctx->aead_spawn.base, alg, inst, - CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); + crypto_set_aead_spawn(&ctx->aead_spawn, aead_crypto_instance(inst)); + err = crypto_grab_aead(&ctx->aead_spawn, name, type, mask); if (err) goto out_free_inst; - type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; - if (alg->cra_flags & CRYPTO_ALG_INTERNAL) - type |= CRYPTO_ALG_INTERNAL; - inst->alg.cra_flags = type; - inst->alg.cra_type = alg->cra_type; - inst->alg.cra_ctxsize = sizeof(struct cryptd_aead_ctx); - inst->alg.cra_init = cryptd_aead_init_tfm; - inst->alg.cra_exit = cryptd_aead_exit_tfm; - inst->alg.cra_aead.setkey = alg->cra_aead.setkey; - inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize; - inst->alg.cra_aead.geniv = alg->cra_aead.geniv; - inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; - inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; - inst->alg.cra_aead.encrypt = cryptd_aead_encrypt_enqueue; - inst->alg.cra_aead.decrypt = cryptd_aead_decrypt_enqueue; - inst->alg.cra_aead.givencrypt = alg->cra_aead.givencrypt; - inst->alg.cra_aead.givdecrypt = alg->cra_aead.givdecrypt; + alg = crypto_spawn_aead_alg(&ctx->aead_spawn); + err = cryptd_init_instance(aead_crypto_instance(inst), &alg->base); + if (err) + goto out_drop_aead; - err = crypto_register_instance(tmpl, inst); + inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC | + (alg->base.cra_flags & CRYPTO_ALG_INTERNAL); + inst->alg.base.cra_ctxsize = sizeof(struct cryptd_aead_ctx); + + inst->alg.ivsize = crypto_aead_alg_ivsize(alg); + inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); + + inst->alg.init = cryptd_aead_init_tfm; + inst->alg.exit = cryptd_aead_exit_tfm; + inst->alg.setkey = cryptd_aead_setkey; + inst->alg.setauthsize = cryptd_aead_setauthsize; + inst->alg.encrypt = cryptd_aead_encrypt_enqueue; + inst->alg.decrypt = cryptd_aead_decrypt_enqueue; + + err = aead_register_instance(tmpl, inst); if (err) { - crypto_drop_spawn(&ctx->aead_spawn.base); +out_drop_aead: + crypto_drop_aead(&ctx->aead_spawn); out_free_inst: kfree(inst); } -out_put_alg: - crypto_mod_put(alg); return err; } @@ -832,8 +862,8 @@ static void cryptd_free(struct crypto_instance *inst) kfree(ahash_instance(inst)); return; case CRYPTO_ALG_TYPE_AEAD: - crypto_drop_spawn(&aead_ctx->aead_spawn.base); - kfree(inst); + crypto_drop_aead(&aead_ctx->aead_spawn); + kfree(aead_instance(inst)); return; default: crypto_drop_spawn(&ctx->spawn); |