Improve small block cipher performance
authorKurt Roeckx <kurt@roeckx.be>
Sun, 16 Feb 2020 13:44:06 +0000 (14:44 +0100)
committerRichard Levitte <levitte@openssl.org>
Sun, 8 Mar 2020 21:41:38 +0000 (22:41 +0100)
Avoid function calls we don't need to do.

In 1.1.1 we have:
aes-128-cbc     572267.80k   681197.08k   715430.74k   720508.59k   722359.64k   723004.07k

Current master:
aes-128-cbc     460663.70k   631125.66k   701283.58k   719794.52k   724732.59k   726668.63k

new:
aes-128-cbc     582057.64k   684288.62k   715721.90k   724856.15k   717578.24k   727176.53k

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11102)

providers/implementations/ciphers/cipher_aes_ocb.c
providers/implementations/ciphers/ciphercommon.c
providers/implementations/ciphers/ciphercommon_block.c

index 2f85604..3d4863e 100644 (file)
@@ -150,9 +150,14 @@ static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
                                          size_t outsize, const unsigned char *in,
                                          size_t inl, OSSL_ocb_cipher_fn ciph)
 {
-    size_t nextblocks = fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
+    size_t nextblocks;
     size_t outlint = 0;
 
+    if (bufsz != 0)
+        nextblocks = fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
+    else
+        nextblocks = inl & ~(AES_BLOCK_SIZE-1);
+
     if (*bufsz == AES_BLOCK_SIZE) {
         if (outsize < AES_BLOCK_SIZE) {
             ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
@@ -179,7 +184,7 @@ static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
         in += nextblocks;
         inl -= nextblocks;
     }
-    if (!trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
+    if (inl != 0 && !trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
         /* PROVerr already called */
         return 0;
     }
index 967622c..33afa57 100644 (file)
@@ -176,7 +176,12 @@ int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
     size_t outlint = 0;
     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
     size_t blksz = ctx->blocksize;
-    size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
+    size_t nextblocks;
+
+    if (ctx->bufsz != 0)
+        nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
+    else
+        nextblocks = inl & ~(blksz-1);
 
     /*
      * If we're decrypting and we end an update on a block boundary we hold
@@ -218,7 +223,7 @@ int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
         in += nextblocks;
         inl -= nextblocks;
     }
-    if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
+    if (inl != 0 && !trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
         /* ERR_raise already called */
         return 0;
     }
index eff9484..ee54f48 100644 (file)
@@ -35,20 +35,17 @@ size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
                  const unsigned char **in, size_t *inlen)
 {
     size_t blockmask = ~(blocksize - 1);
+    size_t bufremain = blocksize - *buflen;
 
     assert(*buflen <= blocksize);
     assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
 
-    if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) {
-        size_t bufremain = blocksize - *buflen;
-
-        if (*inlen < bufremain)
-            bufremain = *inlen;
-        memcpy(buf + *buflen, *in, bufremain);
-        *in += bufremain;
-        *inlen -= bufremain;
-        *buflen += bufremain;
-    }
+    if (*inlen < bufremain)
+        bufremain = *inlen;
+    memcpy(buf + *buflen, *in, bufremain);
+    *in += bufremain;
+    *inlen -= bufremain;
+    *buflen += bufremain;
 
     return *inlen & blockmask;
 }