Skip to content

Commit

Permalink
tpm2: Use EVP functions for symmetric crypto when calculating CMAC
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Berger <[email protected]>
  • Loading branch information
stefanberger committed Feb 28, 2023
1 parent 96c47e2 commit 3822b59
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
73 changes: 73 additions & 0 deletions src/tpm2/crypto/openssl/CryptCmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() */
Expand Down Expand Up @@ -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 */
Expand All @@ -130,11 +134,37 @@ CryptCmacData(
default:
FAIL(FATAL_ERROR_INTERNAL);
}
#else
evpfunc evpfn;
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;

evpfn = GetEVPCipher(algorithm, keySizeInBits, TPM_ALG_ECB, key,
keyToUse, &keyToUseLen);

if (!evpfn ||
(evp_cipher = evpfn()) == NULL ||
(ctx = EVP_CIPHER_CTX_new()) == NULL ||
(inl = EVP_CIPHER_get_block_size(evpfn())) <= 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);
Expand All @@ -143,8 +173,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() */
Expand All @@ -163,24 +197,52 @@ 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
evpfunc evpfn;
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)
default:
return 0;
}
ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer);
#else
evpfn = GetEVPCipher(algorithm, keySizeInBits, TPM_ALG_ECB, key,
keyToUse, &keyToUseLen);

if (!evpfn ||
(evp_cipher = evpfn()) == NULL ||
(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;
Expand All @@ -204,12 +266,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;
}

Expand Down
3 changes: 1 addition & 2 deletions src/tpm2/crypto/openssl/TpmToOsslDesSupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "Tpm.h"
#include "Helpers_fp.h" // libtpms added
#if (defined SYM_LIB_OSSL) && ALG_TDES
#if OPENSSL_VERSION_NUMBER < 0x30000000L
/* B.2.3.1.3. Functions */
/* B.2.3.1.3.1. TDES_set_encyrpt_key() */
/* This function makes creation of a TDES key look like the creation of a key for any of the other
Expand Down Expand Up @@ -103,8 +104,6 @@ void TDES_encrypt(
DES_ENCRYPT);
}

#if OPENSSL_VERSION_NUMBER < 0x30000000L

#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
Expand Down

0 comments on commit 3822b59

Please sign in to comment.