tpm2: Fix issue in CryptParameterEncryption() (TPM 2 errata v1.4)

Sync with upstream to fix issue in CryptParameterEncryption() from TPM 2
errate v1.4 2.6.1:

"The functions CryptParameterEncryption() and CryptParameterDecryption() in
the reference code in Part 4, 10.2.6.6.5 and 10.2.6.6.6 do not correctly
check the size of the parameter buffer to be encrypted or decrypted. To fix
the issue, the functions should be corrected to check that the parameter
buffer (a TPM2B type field) is at least 2 bytes in length and should use
the function UINT16_Unmarshal() to read the size of the buffer instead of"
BYTE_ARRAY_TO_UINT16().

[...]

The fixed CryptParameterEncryption() function will enter failure mode and
return TPM_RC_FAILURE if the internal response buffer does not contain
enough data for the UINT16 size field."

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2023-03-06 16:24:42 -05:00 committed by Stefan Berger
parent 9425f82960
commit c9f9fc52cf
5 changed files with 63 additions and 39 deletions

View File

@ -755,6 +755,7 @@ void
CryptParameterEncryption(
TPM_HANDLE handle, // IN: encrypt session handle
TPM2B *nonceCaller, // IN: nonce caller
INT32 bufferSize, // IN: size of parameter buffer
UINT16 leadingSizeInByte, // IN: the size of the leading size field in
// bytes
TPM2B_AUTH *extraKey, // IN: additional key material other than
@ -766,28 +767,29 @@ CryptParameterEncryption(
TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer)
+ sizeof(session->sessionKey.t.buffer)));
TPM2B_TEMP_KEY key; // encryption key
UINT32 cipherSize = 0; // size of cipher text
// Retrieve encrypted data size.
if(leadingSizeInByte == 2)
{
// Extract the first two bytes as the size field as the data size
// encrypt
cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
// advance the buffer
buffer = &buffer[2];
}
#ifdef TPM4B
else if(leadingSizeInByte == 4)
{
// use the first four bytes to indicate the number of bytes to encrypt
cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
//advance pointer
buffer = &buffer[4];
}
#endif
else
UINT16 cipherSize = 0; // size of cipher text
if(bufferSize < leadingSizeInByte)
{
FAIL(FATAL_ERROR_INTERNAL);
return;
}
// Parameter encryption for a non-2B is not supported.
if(leadingSizeInByte != 2)
{
FAIL(FATAL_ERROR_INTERNAL);
return;
}
// Retrieve encrypted data size.
if(UINT16_Unmarshal(&cipherSize, &buffer, &bufferSize) != TPM_RC_SUCCESS)
{
FAIL(FATAL_ERROR_INTERNAL);
return;
}
if(cipherSize > bufferSize)
{
FAIL(FATAL_ERROR_INTERNAL);
return;
}
// Compute encryption key by concatenating sessionKey with extra key
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
@ -795,14 +797,21 @@ CryptParameterEncryption(
if(session->symmetric.algorithm == TPM_ALG_XOR)
// XOR parameter encryption formulation:
// XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
CryptXORObfuscation(session->authHashAlg, &(key.b),
CryptXORObfuscation(session->authHashAlg,
&(key.b),
&(session->nonceTPM.b),
nonceCaller, cipherSize, buffer);
nonceCaller,
(UINT32)cipherSize,
buffer);
else
ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
session->symmetric.keyBits.aes, &(key.b),
nonceCaller, &(session->nonceTPM.b),
cipherSize, buffer);
ParmEncryptSym(session->symmetric.algorithm,
session->authHashAlg,
session->symmetric.keyBits.aes,
&(key.b),
nonceCaller,
&(session->nonceTPM.b),
(UINT32)cipherSize,
buffer);
return;
}
/* 10.2.6.6.6 CryptParameterDecryption() */

View File

@ -3,7 +3,6 @@
/* ExecCommand */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: ExecCommand.c 1600 2020-03-30 22:08:01Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +54,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 - 2020 */
/* (c) Copyright IBM Corp. and others, 2016 - 2023 */
/* */
/********************************************************************************/
@ -276,7 +275,11 @@ ExecuteCommand(
if(result != TPM_RC_SUCCESS)
goto Cleanup;
// Build the session area at the end of the parameter area.
BuildResponseSession(&command);
result = BuildResponseSession(&command);
if(result != TPM_RC_SUCCESS)
{
goto Cleanup;
}
Cleanup:
if(g_clearOrderly == TRUE
&& NV_IS_ORDERLY)

View File

@ -3,7 +3,6 @@
/* Process the Authorization Sessions */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SessionProcess.c 1658 2021-01-22 23:14:01Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +54,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 - 2021 */
/* (c) Copyright IBM Corp. and others, 2016 - 2023 */
/* */
/********************************************************************************/
@ -1880,12 +1879,13 @@ UpdateAllNonceTPM(
in the response buffer to be filled. This is where the authorization sessions will go, if
any. command->parameterSize is the number of bytes that have been marshaled as parameters in the
output buffer. */
void
TPM_RC
BuildResponseSession(
COMMAND *command // IN: structure that has relevant command
// information
)
{
TPM_RC result = TPM_RC_SUCCESS;
pAssert(command->authSize == 0);
// Reset the parameter buffer to point to the start of the parameters so that
// there is a starting point for any rpHash that might be generated and so there
@ -1915,11 +1915,23 @@ BuildResponseSession(
&extraKey);
}
size = EncryptSize(command->index);
// This function operates on internally-generated data that is
// expected to be well-formed for parameter encryption.
// In the event that there is a bug elsewhere in the code and the
// input data is not well-formed, CryptParameterEncryption will
// put the TPM into failure mode instead of allowing the out-of-
// band write.
CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex],
&s_nonceCaller[s_encryptSessionIndex].b,
command->parameterSize,
(UINT16)size,
&extraKey,
command->parameterBuffer);
if(g_inFailureMode)
{
result = TPM_RC_FAILURE;
goto Cleanup;
}
}
}
// Audit sessions should be processed regardless of the tag because
@ -1969,7 +1981,8 @@ BuildResponseSession(
SessionFlush(s_sessionHandles[i]);
}
}
return;
Cleanup:
return result;
}
/* 6.4.5.13 SessionRemoveAssociationToHandle() */
/* This function deals with the case where an entity associated with an authorization is deleted

View File

@ -3,7 +3,6 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SessionProcess_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +54,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016 - 2023 */
/* */
/********************************************************************************/
@ -83,7 +82,7 @@ TPM_RC
CheckAuthNoSession(
COMMAND *command // IN: command parsing structure
);
void
TPM_RC
BuildResponseSession(
COMMAND *command // IN: structure that has relevant command
// information

View File

@ -3,7 +3,6 @@
/* Interfaces to the CryptoEngine */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptUtil_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +54,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 - 2019 */
/* (c) Copyright IBM Corp. and others, 2016 - 2023 */
/* */
/********************************************************************************/
@ -131,6 +130,7 @@ void
CryptParameterEncryption(
TPM_HANDLE handle, // IN: encrypt session handle
TPM2B *nonceCaller, // IN: nonce caller
INT32 bufferSize, // IN: size of parameter buffer
UINT16 leadingSizeInByte, // IN: the size of the leading size field in
// bytes
TPM2B_AUTH *extraKey, // IN: additional key material other than
@ -141,7 +141,7 @@ TPM_RC
CryptParameterDecryption(
TPM_HANDLE handle, // IN: encrypted session handle
TPM2B *nonceCaller, // IN: nonce caller
UINT32 bufferSize, // IN: size of parameter buffer
INT32 bufferSize, // IN: size of parameter buffer
UINT16 leadingSizeInByte, // IN: the size of the leading size field in
// byte
TPM2B_AUTH *extraKey, // IN: the authValue