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 <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21102)
This commit is contained in:
fisher.yu 2023-05-11 06:43:57 +00:00 committed by Pauli
parent fd54fadba6
commit dc19f2f622

View File

@ -20,6 +20,7 @@
#include <openssl/cmac.h>
#include <openssl/err.h>
#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);