diff options
Diffstat (limited to 'crypto/chainiv.c')
-rw-r--r-- | crypto/chainiv.c | 66 |
1 files changed, 9 insertions, 57 deletions
diff --git a/crypto/chainiv.c b/crypto/chainiv.c index 63c17d5992f7..be0bd521c46f 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -80,35 +80,15 @@ unlock: return err; } -static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) +static int chainiv_init_common(struct crypto_tfm *tfm, char iv[]) { - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - spin_lock_bh(&ctx->lock); - if (crypto_ablkcipher_crt(geniv)->givencrypt != - chainiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - spin_unlock_bh(&ctx->lock); + struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - if (err) - return err; - - return chainiv_givencrypt(req); -} - -static int chainiv_init_common(struct crypto_tfm *tfm) -{ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); - return skcipher_geniv_init(tfm); + return crypto_rng_get_bytes(crypto_default_rng, iv, + crypto_ablkcipher_ivsize(geniv)) ?: + skcipher_geniv_init(tfm); } static int chainiv_init(struct crypto_tfm *tfm) @@ -117,7 +97,7 @@ static int chainiv_init(struct crypto_tfm *tfm) spin_lock_init(&ctx->lock); - return chainiv_init_common(tfm); + return chainiv_init_common(tfm, ctx->iv); } static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx) @@ -205,33 +185,6 @@ postpone: return async_chainiv_postpone_request(req); } -static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) - goto out; - - if (crypto_ablkcipher_crt(geniv)->givencrypt != - async_chainiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - clear_bit(CHAINIV_STATE_INUSE, &ctx->state); - - if (err) - return err; - -out: - return async_chainiv_givencrypt(req); -} - static void async_chainiv_do_postponed(struct work_struct *work) { struct async_chainiv_ctx *ctx = container_of(work, @@ -270,7 +223,7 @@ static int async_chainiv_init(struct crypto_tfm *tfm) crypto_init_queue(&ctx->queue, 100); INIT_WORK(&ctx->postponed, async_chainiv_do_postponed); - return chainiv_init_common(tfm); + return chainiv_init_common(tfm, ctx->iv); } static void async_chainiv_exit(struct crypto_tfm *tfm) @@ -302,7 +255,7 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) if (IS_ERR(inst)) goto put_rng; - inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt; inst->alg.cra_init = chainiv_init; inst->alg.cra_exit = skcipher_geniv_exit; @@ -312,8 +265,7 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) if (!crypto_requires_sync(algt->type, algt->mask)) { inst->alg.cra_flags |= CRYPTO_ALG_ASYNC; - inst->alg.cra_ablkcipher.givencrypt = - async_chainiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = async_chainiv_givencrypt; inst->alg.cra_init = async_chainiv_init; inst->alg.cra_exit = async_chainiv_exit; |