From 5e485d549d2e305f4e49f4789273896f6561e93b Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Feb 2023 18:46:11 -0500 Subject: [PATCH 1/2] tpm2: Use EVP API for DES in some cases Signed-off-by: Stefan Berger --- src/tpm2/crypto/openssl/CryptSym.c | 8 +++++ src/tpm2/crypto/openssl/Helpers.c | 34 +++++++++++++++++++ src/tpm2/crypto/openssl/Helpers_fp.h | 11 ++++++ src/tpm2/crypto/openssl/TpmToOsslDesSupport.c | 27 +++++++++++++++ .../crypto/openssl/TpmToOsslDesSupport_fp.h | 11 ++++++ 5 files changed, 91 insertions(+) diff --git a/src/tpm2/crypto/openssl/CryptSym.c b/src/tpm2/crypto/openssl/CryptSym.c index 756102cff..5059506a4 100644 --- a/src/tpm2/crypto/openssl/CryptSym.c +++ b/src/tpm2/crypto/openssl/CryptSym.c @@ -494,18 +494,26 @@ static void TDES_CTR(const BYTE *key, // IN INT16 blockSize // IN ) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L tpmCryptKeySchedule_t keySchedule; +#endif int i; BYTE tmp[MAX_SYM_BLOCK_SIZE]; BYTE *pT; +#if OPENSSL_VERSION_NUMBER < 0x30000000L TDES_set_encrypt_key(key, keySizeInBits, (tpmKeyScheduleTDES *)&keySchedule.tdes); +#endif for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the IV(counter) +#if OPENSSL_VERSION_NUMBER < 0x30000000L TDES_encrypt(iv, tmp, (tpmKeyScheduleTDES *)&keySchedule.tdes); +#else + TDES_crypt(key, keySizeInBits, iv, tmp, TRUE); +#endif //increment the counter (counter is big-endian so start at end) for(i = blockSize - 1; i >= 0; i--) if((iv[i] += 1) != 0) diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c index 4ad0e2f00..77713913c 100644 --- a/src/tpm2/crypto/openssl/Helpers.c +++ b/src/tpm2/crypto/openssl/Helpers.c @@ -366,6 +366,40 @@ TPM_RC DoEVPGetIV( #endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC +TPM_RC +DoEVPCryptOneBlock( + EVP_CIPHER_CTX *ctx, // IN: optional context + const EVP_CIPHER *evp_cipher, // IN: EVP_CIPHER to use + const BYTE *key, // IN: key whose size is suitable for evpfn + const BYTE *in, // IN: input block + int inl, // IN: size of input block in bytes + BYTE *out, // OUT: output block; must be different memory than in + BOOL encrypt // IN: encrypto (TRUE) or decrypt (FALSE) + ) +{ + EVP_CIPHER_CTX *l_ctx = NULL; + TPM_RC retVal = 0; + int outlen1 = 0; + int outlen2 = 0; + + l_ctx = ctx ? ctx : EVP_CIPHER_CTX_new(); + if (!l_ctx) + ERROR_RETURN(TPM_RC_MEMORY); + + if (EVP_CipherInit(l_ctx, evp_cipher, key, NULL, encrypt) != 1 || + EVP_CIPHER_CTX_set_padding(l_ctx, 0) != 1 || + EVP_CipherUpdate(l_ctx, out, &outlen1, in, inl) != 1 || + EVP_CipherFinal_ex(l_ctx, out + outlen1, &outlen2) != 1 || + outlen1 + outlen2 != inl) + ERROR_RETURN(TPM_RC_FAILURE); + + Exit: + if (!ctx) + EVP_CIPHER_CTX_free(l_ctx); + + return retVal; +} + #if USE_OPENSSL_FUNCTIONS_EC BOOL OpenSSLEccGetPrivate( diff --git a/src/tpm2/crypto/openssl/Helpers_fp.h b/src/tpm2/crypto/openssl/Helpers_fp.h index 3fa0f96ab..cbd1fa2f7 100644 --- a/src/tpm2/crypto/openssl/Helpers_fp.h +++ b/src/tpm2/crypto/openssl/Helpers_fp.h @@ -87,6 +87,17 @@ TPM_RC DoEVPGetIV( #endif +TPM_RC +DoEVPCryptOneBlock( + EVP_CIPHER_CTX *ctx, // IN: optional context + const EVP_CIPHER *evp_cipher, // IN: crypto function + const BYTE *key, // IN: key whose size is suitable for evpfn + const BYTE *in, // IN: input block + int inl, // IN: size of input block in bytes + BYTE *out, // OUT: output block; must be different memory than in + BOOL encrypt // IN: encrypto (TRUE) or decrypt (FALSE) + ); + #if USE_OPENSSL_FUNCTIONS_EC BOOL OpenSSLEccGetPrivate( bigNum dOut, // OUT: the qualified random value diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c index d27aad270..f95b50e8e 100644 --- a/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c +++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c @@ -65,6 +65,7 @@ library. */ /* B.2.3.1.2. Defines and Includes */ #include "Tpm.h" +#include "Helpers_fp.h" // libtpms added #if (defined SYM_LIB_OSSL) && ALG_TDES /* B.2.3.1.3. Functions */ /* B.2.3.1.3.1. TDES_set_encyrpt_key() */ @@ -101,6 +102,7 @@ void TDES_encrypt( &ks[0], &ks[1], &ks[2], DES_ENCRYPT); } + #if !USE_OPENSSL_FUNCTIONS_SYMMETRIC /* B.2.3.1.3.3. TDES_decrypt() */ /* As with TDES_encypt() this function bridges between the TPM single schedule model and the @@ -116,4 +118,29 @@ void TDES_decrypt( DES_DECRYPT); } #endif // !USE_OPENSSL_FUNCTIONS_SYMMETRIC + +#if OPENSSL_VERSION_NUMBER > 0x30000000L + +void TDES_crypt( + const BYTE *key, + UINT16 keySizeInBits, + const BYTE *in, + BYTE *out, + BOOL encrypt + ) +{ + static const EVP_CIPHER *evp_cipher_cached = NULL; + + if (!evp_cipher_cached) { + evp_cipher_cached = EVP_des_ede3_ecb(); + pAssert(evp_cipher_cached); + } + + if (DoEVPCryptOneBlock(NULL, evp_cipher_cached, key, in, sizeof(DES_cblock), + out, encrypt)) + pAssert(false) +} + +#endif // OPENSSL_VERSION_NUMBER + #endif // SYM_LIB_OSSL diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h index 4338fe630..54b71bd65 100644 --- a/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h +++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h @@ -79,5 +79,16 @@ void TDES_decrypt( tpmKeyScheduleTDES *ks ); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +void TDES_crypt( + const BYTE *key, + UINT16 keySizeInBits, + const BYTE *in, + BYTE *out, + BOOL encrypt + ); + +#endif #endif From 233e81bb735852feaa1abca9b3d75dda80fa359e Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 10 Feb 2023 11:27:48 -0500 Subject: [PATCH 2/2] tpm2: Use EVP functions for symmetric crypto when calculating CMAC Signed-off-by: Stefan Berger --- src/tpm2/crypto/openssl/CryptCmac.c | 69 ++++++++++++++++++++++++++++ src/tpm2/crypto/openssl/Helpers.c | 53 +++++++++++---------- src/tpm2/crypto/openssl/Helpers_fp.h | 18 ++++---- 3 files changed, 105 insertions(+), 35 deletions(-) diff --git a/src/tpm2/crypto/openssl/CryptCmac.c b/src/tpm2/crypto/openssl/CryptCmac.c index 795e36867..8fadbda2b 100644 --- a/src/tpm2/crypto/openssl/CryptCmac.c +++ b/src/tpm2/crypto/openssl/CryptCmac.c @@ -68,6 +68,9 @@ #define _CRYPT_HASH_C_ #include "Tpm.h" #include "CryptSym.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include "Helpers_fp.h" +#endif #if ALG_CMAC /* 10.2.6.3 Functions */ /* 10.2.6.3.1 CryptCmacStart() */ @@ -118,6 +121,7 @@ CryptCmacData( TPM_ALG_ID algorithm = cmacState->symAlg; BYTE *key = cmacState->symKey.t.buffer; UINT16 keySizeInBits = cmacState->keySizeBits; +#if OPENSSL_VERSION_NUMBER < 0x30000000L tpmCryptKeySchedule_t keySchedule; TpmCryptSetSymKeyCall_t encrypt; TpmCryptSymFinal_t final; /* libtpms added */ @@ -130,11 +134,35 @@ CryptCmacData( default: FAIL(FATAL_ERROR_INTERNAL); } +#else + const EVP_CIPHER *evp_cipher; + BYTE keyToUse[MAX_SYM_KEY_BYTES]; + UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); + EVP_CIPHER_CTX *ctx; + BYTE out[MAX_SYM_BLOCK_SIZE]; + int inl; + + evp_cipher = GetEVPCipher(algorithm, keySizeInBits, TPM_ALG_ECB, key, + keyToUse, &keyToUseLen); + + if (!evp_cipher || + (ctx = EVP_CIPHER_CTX_new()) == NULL || + (inl = EVP_CIPHER_get_block_size(evp_cipher)) <= 0) + pAssert(false); +#endif + while(size > 0) { if(cmacState->bcount == cmacState->iv.t.size) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer); +#else + if (DoEVPCryptOneBlock(ctx, evp_cipher, keyToUse, cmacState->iv.t.buffer, + inl, out, TRUE)) + pAssert(false); + memcpy(cmacState->iv.t.buffer, out, inl); +#endif cmacState->bcount = 0; } for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size); @@ -143,8 +171,12 @@ CryptCmacData( cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; } } +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (final) // libtpms added begin FINAL(&keySchedule); // libtpms added end +#else + EVP_CIPHER_CTX_free(ctx); +#endif } /* 10.2.6.3.3 CryptCmacEnd() */ @@ -163,17 +195,29 @@ CryptCmacEnd( TPM_ALG_ID algorithm = cState->symAlg; BYTE *key = cState->symKey.t.buffer; UINT16 keySizeInBits = cState->keySizeBits; +#if OPENSSL_VERSION_NUMBER < 0x30000000L tpmCryptKeySchedule_t keySchedule; TpmCryptSetSymKeyCall_t encrypt; TpmCryptSymFinal_t final; // libtpms added +#else + const EVP_CIPHER *evp_cipher; + BYTE keyToUse[MAX_SYM_KEY_BYTES]; + UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); + EVP_CIPHER_CTX *ctx; + BYTE out[MAX_SYM_BLOCK_SIZE]; + int inl; +#endif TPM2B_IV subkey = {{0, {0}}}; BOOL xorVal; UINT16 i; +#if OPENSSL_VERSION_NUMBER < 0x30000000L memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ +#endif subkey.t.size = cState->iv.t.size; // Encrypt a block of zero // Set up the encryption values based on the algorithm +#if OPENSSL_VERSION_NUMBER < 0x30000000L switch (algorithm) { FOR_EACH_SYM(ENCRYPT_CASE) @@ -181,6 +225,20 @@ CryptCmacEnd( return 0; } ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer); +#else + evp_cipher = GetEVPCipher(algorithm, keySizeInBits, TPM_ALG_ECB, key, + keyToUse, &keyToUseLen); + + if (!evp_cipher || + (ctx = EVP_CIPHER_CTX_new()) == NULL || + (inl = EVP_CIPHER_get_block_size(evp_cipher)) <= 0) + pAssert(false); + + if (DoEVPCryptOneBlock(ctx, evp_cipher, keyToUse, subkey.t.buffer, inl, + out, TRUE)) + pAssert(false); + memcpy(subkey.t.buffer, out, inl); +#endif // shift left by 1 and XOR with 0x0...87 if the MSb was 0 xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; @@ -204,12 +262,23 @@ CryptCmacEnd( // XOR the subkey into the IV for(i = 0; i < subkey.t.size; i++) cState->iv.t.buffer[i] ^= subkey.t.buffer[i]; +#if OPENSSL_VERSION_NUMBER < 0x30000000L ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); +#else + if (DoEVPCryptOneBlock(ctx, evp_cipher, keyToUse, cState->iv.t.buffer, inl, + out, TRUE)) + pAssert(false); + memcpy(cState->iv.t.buffer, out, inl); +#endif i = (UINT16)MIN(cState->iv.t.size, outSize); MemoryCopy(outBuffer, cState->iv.t.buffer, i); +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (final) // libtpms added begin FINAL(&keySchedule); // libtpms added end +#else + EVP_CIPHER_CTX_free(ctx); +#endif return i; } diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c index 77713913c..de73a2fc1 100644 --- a/src/tpm2/crypto/openssl/Helpers.c +++ b/src/tpm2/crypto/openssl/Helpers.c @@ -115,6 +115,32 @@ OpenSSLCryptGenerateKeyDes( return retVal; } +TPM_RC DoEVPGetIV( + EVP_CIPHER_CTX *ctx, // IN: required context + unsigned char *iv, // IN: pointer to buffer for IV + size_t iv_len // IN: size of the buffer + ) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM params[] = { + OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_UPDATED_IV, &iv, iv_len), + OSSL_PARAM_END + }; + if (EVP_CIPHER_CTX_get_params(ctx, params) != 1) + return TPM_RC_FAILURE; +#else + const unsigned char *c_iv; + + c_iv = EVP_CIPHER_CTX_iv(ctx); + if (!c_iv) + return TPM_RC_FAILURE; + memcpy(iv, c_iv, iv_len); +#endif // OPENSSL_VERSION_NUMBER + + return 0; +} + +#endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC #define __NUM_ALGS 4 /* AES, TDES, Camellia, SM4 */ #define __NUM_MODES 5 /* CTR, OFB, CBC, CFB, ECB */ @@ -339,33 +365,6 @@ GetEVPCipher(TPM_ALG_ID algorithm, // IN return GetCachedEVPCipher(evpfn, algIdx, mode, i); } -TPM_RC DoEVPGetIV( - EVP_CIPHER_CTX *ctx, // IN: required context - unsigned char *iv, // IN: pointer to buffer for IV - size_t iv_len // IN: size of the buffer - ) -{ -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - OSSL_PARAM params[] = { - OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_UPDATED_IV, &iv, iv_len), - OSSL_PARAM_END - }; - if (EVP_CIPHER_CTX_get_params(ctx, params) != 1) - return TPM_RC_FAILURE; -#else - const unsigned char *c_iv; - - c_iv = EVP_CIPHER_CTX_iv(ctx); - if (!c_iv) - return TPM_RC_FAILURE; - memcpy(iv, c_iv, iv_len); -#endif // OPENSSL_VERSION_NUMBER - - return 0; -} - -#endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC - TPM_RC DoEVPCryptOneBlock( EVP_CIPHER_CTX *ctx, // IN: optional context diff --git a/src/tpm2/crypto/openssl/Helpers_fp.h b/src/tpm2/crypto/openssl/Helpers_fp.h index cbd1fa2f7..68143db13 100644 --- a/src/tpm2/crypto/openssl/Helpers_fp.h +++ b/src/tpm2/crypto/openssl/Helpers_fp.h @@ -71,6 +71,16 @@ OpenSSLCryptGenerateKeyDes( TPMT_SENSITIVE *sensitive // OUT: sensitive area ); +TPM_RC DoEVPGetIV( + EVP_CIPHER_CTX *ctx, // IN: required context + unsigned char *iv, // IN: pointer to buffer for IV + size_t iv_len // IN: size of the buffer + ); +#endif + +/* The following functions to support symmetric crypto using + OpenSSL are needed for CMAC for example */ + const EVP_CIPHER *GetEVPCipher(TPM_ALG_ID algorithm, // IN UINT16 keySizeInBits, // IN TPM_ALG_ID mode, // IN @@ -79,14 +89,6 @@ const EVP_CIPHER *GetEVPCipher(TPM_ALG_ID algorithm, // IN UINT16 *keyToUseLen // IN/OUT ); -TPM_RC DoEVPGetIV( - EVP_CIPHER_CTX *ctx, // IN: required context - unsigned char *iv, // IN: pointer to buffer for IV - size_t iv_len // IN: size of the buffer - ); - -#endif - TPM_RC DoEVPCryptOneBlock( EVP_CIPHER_CTX *ctx, // IN: optional context