DRBG is starting an async. crypto op and waiting for it complete.
Move it over to generic code doing the same.

The code now also passes CRYPTO_TFM_REQ_MAY_SLEEP flag indicating
crypto request memory allocation may use GFP_KERNEL which should
be perfectly fine as the code is obviously sleeping for the
completion of the request any way.

Signed-off-by: Gilad Ben-Yossef <gi...@benyossef.com>
---
 crypto/drbg.c         | 34 ++++++++--------------------------
 include/crypto/drbg.h |  3 +--
 2 files changed, 9 insertions(+), 28 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index cdb27ac..101d9f0 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1651,16 +1651,6 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg)
        return 0;
 }
 
-static void drbg_skcipher_cb(struct crypto_async_request *req, int error)
-{
-       struct drbg_state *drbg = req->data;
-
-       if (error == -EINPROGRESS)
-               return;
-       drbg->ctr_async_err = error;
-       complete(&drbg->ctr_completion);
-}
-
 static int drbg_init_sym_kernel(struct drbg_state *drbg)
 {
        struct crypto_cipher *tfm;
@@ -1699,8 +1689,9 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg)
                return -ENOMEM;
        }
        drbg->ctr_req = req;
-       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       drbg_skcipher_cb, drbg);
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+                                               CRYPTO_TFM_REQ_MAY_SLEEP,
+                                       crypto_req_done, &drbg->ctr_wait);
 
        alignmask = crypto_skcipher_alignmask(sk_tfm);
        drbg->ctr_null_value_buf = kzalloc(DRBG_CTR_NULL_LEN + alignmask,
@@ -1761,21 +1752,12 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
                /* Output buffer may not be valid for SGL, use scratchpad */
                skcipher_request_set_crypt(drbg->ctr_req, &sg_in, &sg_out,
                                           cryptlen, drbg->V);
-               ret = crypto_skcipher_encrypt(drbg->ctr_req);
-               switch (ret) {
-               case 0:
-                       break;
-               case -EINPROGRESS:
-               case -EBUSY:
-                       wait_for_completion(&drbg->ctr_completion);
-                       if (!drbg->ctr_async_err) {
-                               reinit_completion(&drbg->ctr_completion);
-                               break;
-                       }
-               default:
+               ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req),
+                                       &drbg->ctr_wait);
+               if (ret)
                        goto out;
-               }
-               init_completion(&drbg->ctr_completion);
+
+               crypto_init_wait(&drbg->ctr_wait);
 
                memcpy(outbuf, drbg->outscratchpad, cryptlen);
 
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 22f884c..8f94110 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -126,8 +126,7 @@ struct drbg_state {
        __u8 *ctr_null_value;                   /* CTR mode aligned zero buf */
        __u8 *outscratchpadbuf;                 /* CTR mode output scratchpad */
         __u8 *outscratchpad;                   /* CTR mode aligned outbuf */
-       struct completion ctr_completion;       /* CTR mode async handler */
-       int ctr_async_err;                      /* CTR mode async error */
+       struct crypto_wait ctr_wait;            /* CTR mode async wait obj */
 
        bool seeded;            /* DRBG fully seeded? */
        bool pr;                /* Prediction resistance enabled? */
-- 
2.1.4

Reply via email to