tpm2: Add a caching layer to GetEVPCipher() helper function

Add a caching layer to GetEVPCipher() to avoid having to call evpfn()
mulitple times. Instead, return the 'const EVP_CIPHER *' that a single
call to evpfn() (for a particular algorithm + mode + key size) returned
and cache it for subsequent calls.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2023-02-28 10:40:44 -05:00 committed by Stefan Berger
parent 66d178b981
commit b87306ca12
3 changed files with 77 additions and 28 deletions

View File

@ -540,7 +540,7 @@ CryptSymmetricEncrypt(
INT16 blockSize;
BYTE *iv;
BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
evpfunc evpfn;
const EVP_CIPHER *evp_cipher;
EVP_CIPHER_CTX *ctx = NULL;
int outlen1 = 0;
int outlen2 = 0;
@ -580,9 +580,9 @@ CryptSymmetricEncrypt(
return TPM_RC_SIZE;
}
evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key,
keyToUse, &keyToUseLen);
if (evpfn == NULL)
evp_cipher = GetEVPCipher(algorithm, keySizeInBits, mode, key,
keyToUse, &keyToUseLen);
if (evp_cipher == NULL)
return TPM_RC_FAILURE;
if (dIn == dOut) {
@ -605,7 +605,7 @@ CryptSymmetricEncrypt(
ctx = EVP_CIPHER_CTX_new();
if (!ctx ||
EVP_EncryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 ||
EVP_EncryptInit_ex(ctx, evp_cipher, NULL, keyToUse, iv) != 1 ||
EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 ||
EVP_EncryptUpdate(ctx, pOut, &outlen1, dIn, dSize) != 1)
ERROR_RETURN(TPM_RC_FAILURE);
@ -656,7 +656,7 @@ CryptSymmetricDecrypt(
INT16 blockSize;
BYTE *iv;
BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
evpfunc evpfn;
const EVP_CIPHER *evp_cipher;
EVP_CIPHER_CTX *ctx = NULL;
int outlen1 = 0;
int outlen2 = 0;
@ -704,9 +704,9 @@ CryptSymmetricDecrypt(
break;
}
evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key,
keyToUse, &keyToUseLen);
if (evpfn == NULL)
evp_cipher = GetEVPCipher(algorithm, keySizeInBits, mode, key,
keyToUse, &keyToUseLen);
if (evp_cipher == NULL)
return TPM_RC_FAILURE;
/* a buffer with a 'safety margin' for EVP_DecryptUpdate */
@ -725,7 +725,7 @@ CryptSymmetricDecrypt(
ctx = EVP_CIPHER_CTX_new();
if (!ctx ||
EVP_DecryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 ||
EVP_DecryptInit_ex(ctx, evp_cipher, NULL, keyToUse, iv) != 1 ||
EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 ||
EVP_DecryptUpdate(ctx, buffer, &outlen1, dIn, dSize) != 1)
ERROR_RETURN(TPM_RC_FAILURE);

View File

@ -72,6 +72,8 @@
# include <openssl/param_build.h>
#endif
typedef const EVP_CIPHER *(*evpfunc)(void);
/* to enable RSA_check_key() on private keys set to != 0 */
#ifndef DO_RSA_CHECK_KEY
#define DO_RSA_CHECK_KEY 0
@ -113,17 +115,56 @@ OpenSSLCryptGenerateKeyDes(
return retVal;
}
evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
UINT16 keySizeInBits, // IN
TPM_ALG_ID mode, // IN
const BYTE *key, // IN
BYTE *keyToUse, // OUT same as key or stretched key
UINT16 *keyToUseLen // IN/OUT
)
#define __NUM_ALGS 4 /* AES, TDES, Camellia, SM4 */
#define __NUM_MODES 5 /* CTR, OFB, CBC, CFB, ECB */
#define __NUM_KEYSIZES 3 /* 128, 192, 256 */
static const EVP_CIPHER *evp_cipher_cache[__NUM_ALGS][__NUM_MODES][__NUM_KEYSIZES] = {
{ { NULL, } },
};
static const EVP_CIPHER *
GetCachedEVPCipher(
evpfunc evpfunc, // IN
size_t algIdx, // IN algorithm Index for the cache
TPM_ALG_ID mode, // IN mode
size_t keySizeIdx // IN
)
{
size_t modeIdx = mode - ALG_CTR_VALUE;
const EVP_CIPHER *evp_cipher;
pAssert(algIdx < __NUM_ALGS &&
modeIdx < __NUM_MODES &&
keySizeIdx < __NUM_KEYSIZES);
evp_cipher = evp_cipher_cache[algIdx][modeIdx][keySizeIdx];
if (evp_cipher == NULL) {
evp_cipher = evpfunc();
evp_cipher_cache[algIdx][modeIdx][keySizeIdx] = evp_cipher;
}
return evp_cipher;
}
#undef __NUM_KEYSIZES
#undef __NUM_MODES
#undef __NUM_ALGS
const EVP_CIPHER *
GetEVPCipher(TPM_ALG_ID algorithm, // IN
UINT16 keySizeInBits, // IN
TPM_ALG_ID mode, // IN
const BYTE *key, // IN
BYTE *keyToUse, // OUT same as key or stretched key
UINT16 *keyToUseLen // IN/OUT
)
{
int i;
UINT16 keySizeInBytes = keySizeInBits / 8;
evpfunc evpfn = NULL;
size_t algIdx;
// key size to array index: 128 -> 0, 192 -> 1, 256 -> 2
i = (keySizeInBits >> 6) - 2;
@ -136,7 +177,9 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
switch (algorithm) {
#if ALG_AES
case TPM_ALG_AES:
algIdx = 0;
*keyToUseLen = keySizeInBytes;
switch (mode) {
#if ALG_CTR
case TPM_ALG_CTR:
@ -173,6 +216,7 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
#endif
#if ALG_TDES
case TPM_ALG_TDES:
algIdx = 1;
if (keySizeInBits == 128) {
pAssert(*keyToUseLen >= BITS_TO_BYTES(192))
// stretch the key
@ -212,7 +256,9 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
#if ALG_SM4
case TPM_ALG_SM4:
algIdx = 2;
*keyToUseLen = keySizeInBytes;
switch (mode) {
#if ALG_CTR
case TPM_ALG_CTR:
@ -245,7 +291,9 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
#if ALG_CAMELLIA
case TPM_ALG_CAMELLIA:
algIdx = 3;
*keyToUseLen = keySizeInBytes;
switch (mode) {
#if ALG_CTR
case TPM_ALG_CTR:
@ -282,10 +330,13 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
#endif
}
if (evpfn == NULL)
if (evpfn == NULL) {
MemorySet(keyToUse, 0, *keyToUseLen);
return NULL;
}
return evpfn;
/* get cached result of evpfn() */
return GetCachedEVPCipher(evpfn, algIdx, mode, i);
}
TPM_RC DoEVPGetIV(

View File

@ -71,15 +71,13 @@ OpenSSLCryptGenerateKeyDes(
TPMT_SENSITIVE *sensitive // OUT: sensitive area
);
typedef const EVP_CIPHER *(*evpfunc)(void);
evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
UINT16 keySizeInBits, // IN
TPM_ALG_ID mode, // IN
const BYTE *key, // IN
BYTE *keyToUse, // OUT same as key or stretched key
UINT16 *keyToUseLen // IN/OUT
);
const EVP_CIPHER *GetEVPCipher(TPM_ALG_ID algorithm, // IN
UINT16 keySizeInBits, // IN
TPM_ALG_ID mode, // IN
const BYTE *key, // IN
BYTE *keyToUse, // OUT same as key or stretched key
UINT16 *keyToUseLen // IN/OUT
);
TPM_RC DoEVPGetIV(
EVP_CIPHER_CTX *ctx, // IN: required context