From: fisher.yu Date: Thu, 11 May 2023 06:43:57 +0000 (+0000) Subject: Optimize CMAC_Update for better performance. X-Git-Tag: openssl-3.2.0-alpha1~682 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dc19f2f6223db0578be826d03ba8012cca076d28;p=thirdparty%2Fopenssl.git Optimize CMAC_Update for better performance. Reduce the number of EVP_Cipher function calls in CMAC_Update, to improve performance of CMAC. Below are command and result of performance improvement. COMMAND: openssl speed -cmac ALGORITHM IMPROVEMENT(%): A72 stands for Cortex A72 N1 stands for Neoverse N1 N2 stands for Neoverse N2 A72 N1 N2 x86 aes-128-cbc@256 65.4 54.6 37.9 86.6 aes-128-cbc@1024 156.0 105.6 65.8 197.1 aes-128-cbc@8192 237.7 139.2 80.5 285.8 aes-128-cbc@16384 249.1 143.5 82.2 294.1 aes-192-cbc@256 65.6 46.5 30.9 77.8 aes-192-cbc@1024 154.2 87.5 50.8 167.4 aes-192-cbc@8192 226.5 117.0 60.5 231.7 aes-192-cbc@16384 236.3 120.1 61.7 238.4 aes-256-cbc@256 66.0 40.3 22.2 69.5 aes-256-cbc@1024 136.8 74.6 35.7 142.2 aes-256-cbc@8192 189.7 93.5 41.5 191.7 aes-256-cbc@16384 196.6 95.8 42.2 195.9 des-ede3-cbc@64 6.9 4.4 2.9 7.2 des-ede3-cbc@256 9.3 6.1 4.3 13.1 des-ede3-cbc@1024 10.0 6.4 4.8 14.9 des-ede3-cbc@8192 10.3 6.5 5.1 15.5 des-ede3-cbc@16384 10.3 6.4 5.1 15.5 sm4-cbc@256 9.5 3.0 - 18.0 sm4-cbc@1024 12.3 3.6 - 24.6 sm4-cbc@8192 13.2 3.8 - 27.0 sm4-cbc@16384 13.5 3.8 - 27.2 Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21102) --- diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c index b7cbba90c04..961df0d7191 100644 --- a/crypto/cmac/cmac.c +++ b/crypto/cmac/cmac.c @@ -20,6 +20,7 @@ #include #include +#define LOCAL_BUF_SIZE 2048 struct CMAC_CTX_st { /* Cipher context to use */ EVP_CIPHER_CTX *cctx; @@ -162,6 +163,8 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) { const unsigned char *data = in; int bl; + size_t max_burst_blocks, cipher_blocks; + unsigned char buf[LOCAL_BUF_SIZE]; if (ctx->nlast_block == -1) return 0; @@ -188,11 +191,35 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) return 0; } /* Encrypt all but one of the complete blocks left */ - while (dlen > (size_t)bl) { - if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0) - return 0; - dlen -= bl; - data += bl; + + max_burst_blocks = LOCAL_BUF_SIZE / bl; + cipher_blocks = (dlen - 1) / bl; + if (max_burst_blocks == 0) { + /* + * In case block length is greater than local buffer size, + * use ctx->tbl as cipher output. + */ + while (dlen > (size_t)bl) { + if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0) + return 0; + dlen -= bl; + data += bl; + } + } else { + while (cipher_blocks > max_burst_blocks) { + if (EVP_Cipher(ctx->cctx, buf, data, max_burst_blocks * bl) <= 0) + return 0; + dlen -= max_burst_blocks * bl; + data += max_burst_blocks * bl; + cipher_blocks -= max_burst_blocks; + } + if (cipher_blocks > 0) { + if (EVP_Cipher(ctx->cctx, buf, data, cipher_blocks * bl) <= 0) + return 0; + dlen -= cipher_blocks * bl; + data += cipher_blocks * bl; + memcpy(ctx->tbl, &buf[(cipher_blocks - 1) * bl], bl); + } } /* Copy any data left to last block buffer */ memcpy(ctx->last_block, data, dlen);