The SGL can directly operate caller-provided memory with the exception
of stack memory. The DRBG detects whether the caller provided
non-suitable memory and uses the scratchpad only on those circumstances.

This patch increases the speed of the CTR DRBG by 1 to 3 percent
depending on the buffer size of the output buffer.

Signed-off-by: Stephan Mueller <[email protected]>
---
 crypto/drbg.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index ee302fd229ad..193354e9d207 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1748,14 +1748,20 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
 {
        struct scatterlist *sg_in = &drbg->sg_in, *sg_out = &drbg->sg_out;
        int ret;
+       bool virt_addr_valid = virt_addr_valid(outbuf);
 
        sg_set_buf(sg_in, inbuf, inlen);
-       sg_set_buf(sg_out, drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
 
        while (outlen) {
-               u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN);
+               u32 cryptlen = min_t(u32, inlen, outlen);
 
                /* Output buffer may not be valid for SGL, use scratchpad */
+               if (virt_addr_valid) {
+                       sg_set_buf(sg_out, outbuf, cryptlen);
+               } else {
+                       cryptlen = min_t(u32, cryptlen, DRBG_OUTSCRATCHLEN);
+                       sg_set_buf(sg_out, drbg->outscratchpad, cryptlen);
+               }
                skcipher_request_set_crypt(drbg->ctr_req, sg_in, sg_out,
                                           cryptlen, drbg->V);
                ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req),
@@ -1765,7 +1771,8 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
 
                crypto_init_wait(&drbg->ctr_wait);
 
-               memcpy(outbuf, drbg->outscratchpad, cryptlen);
+               if (!virt_addr_valid)
+                       memcpy(outbuf, drbg->outscratchpad, cryptlen);
 
                outlen -= cryptlen;
                outbuf += cryptlen;
@@ -1773,7 +1780,8 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
        ret = 0;
 
 out:
-       memzero_explicit(drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
+       if (!virt_addr_valid)
+               memzero_explicit(drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
        return ret;
 }
 #endif /* CONFIG_CRYPTO_DRBG_CTR */
-- 
2.17.1




Reply via email to