crypto: chainiv - Move IV seeding into init function
[linux-drm-fsl-dcu.git] / crypto / chainiv.c
index 63c17d5992f79b5a5ed40a526fa58a532eb3e5dc..be0bd521c46f1fa3cda099e3c88f69d26e569a64 100644 (file)
@@ -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;