diff --git a/src/tpm12/tpm_crypto.c b/src/tpm12/tpm_crypto.c index add71c40d..ead5889e6 100644 --- a/src/tpm12/tpm_crypto.c +++ b/src/tpm12/tpm_crypto.c @@ -2136,6 +2136,20 @@ TPM_RESULT TPM_Sha1Context_Load(void **context, if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->num), stream, stream_size); } + /* 'num' is the number of bytes buffered in sha_ctx->data and is used by + OpenSSL as the write offset in SHA1_Update()/SHA1_Final(); it must be + less than the block size, else a later update walks off the context. */ + if ((rc== 0) && contextPresent) { + if (sha_ctx->num >= SHA_CBLOCK) { + printf("TPM_Sha1Context_Load: Error, num %u out of range\n", + sha_ctx->num); + rc = TPM_BAD_PARAMETER; + } + } + if ((rc != 0) && contextPresent && (*context != NULL)) { + free(*context); + *context = NULL; + } return rc; } @@ -2862,9 +2876,10 @@ TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* outpu (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); - /* sanity check encrypted length */ + /* sanity check encrypted length; CBC requires a whole number of blocks, + otherwise AES_cbc_encrypt() reads past the end of the input buffer */ if (rc == 0) { - if (encrypt_length < TPM_AES_BLOCK_SIZE) { + if ((encrypt_length % TPM_AES_BLOCK_SIZE) != 0) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } diff --git a/src/tpm12/tpm_crypto_freebl.c b/src/tpm12/tpm_crypto_freebl.c index 272c26472..5a249897b 100644 --- a/src/tpm12/tpm_crypto_freebl.c +++ b/src/tpm12/tpm_crypto_freebl.c @@ -2323,9 +2323,9 @@ TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* outpu printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); cx = NULL; /* freed @1 */ - /* sanity check encrypted length */ + /* sanity check encrypted length; CBC requires a whole number of blocks */ if (rc == 0) { - if (encrypt_length < TPM_AES_BLOCK_SIZE) { + if ((encrypt_length % TPM_AES_BLOCK_SIZE) != 0) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } diff --git a/src/tpm2/NVDynamic.c b/src/tpm2/NVDynamic.c index aaf227be5..7226150af 100644 --- a/src/tpm2/NVDynamic.c +++ b/src/tpm2/NVDynamic.c @@ -668,6 +668,16 @@ void NvReadObject(NV_REF ref, // IN: points to NV where index is located return; // libtpms changed end } + // libtpms added begin +static void NvReadObjectAttributes(NV_REF ref, // IN: points to NV where index is located, + OBJECT_ATTRIBUTES* attributes // OUT: place to receive the object attributes +) +{ + OBJECT obj = { 0 }; + + NvReadObject(ref, &obj); + *attributes = obj.attributes; +} // libtpms added end //*** NvFindEvict() // This function will return the NV offset of an evict object @@ -1414,10 +1424,13 @@ NvFlushHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. { OBJECT_ATTRIBUTES attributes; // +#if 0 // libtpms changed begin NvRead(&attributes, (UINT32)(currentAddr + sizeof(TPM_HANDLE) + offsetof(OBJECT, attributes)), sizeof(OBJECT_ATTRIBUTES)); +#endif + NvReadObjectAttributes(currentAddr, &attributes); // libtpms changed end // If the evict object belongs to the hierarchy to be flushed... if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET) || (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET) diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c index 7c14bb02c..c53882c17 100644 --- a/src/tpm2/NVMarshal.c +++ b/src/tpm2/NVMarshal.c @@ -4148,6 +4148,9 @@ PERSISTENT_DATA_PPList_Unmarshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *si if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); + /* check array_size for a reasonable maximum that should never be reached */ + if (rc == TPM_RC_SUCCESS && array_size > 1024) + rc = TPM_RC_SIZE; } if (rc == TPM_RC_SUCCESS) { BYTE buf[array_size]; @@ -4216,6 +4219,9 @@ PERSISTENT_DATA_AuditCommands_Unmarshal(PERSISTENT_DATA *data, BYTE **buffer, IN if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); + /* check array_size for a reasonable maximum that should never be reached */ + if (rc == TPM_RC_SUCCESS && array_size > 1024) + rc = TPM_RC_SIZE; } if (rc == TPM_RC_SUCCESS) { BYTE buf[array_size]; @@ -5002,7 +5008,11 @@ USER_NVRAM_Unmarshal(BYTE **buffer, INT32 *size) memset(&obj, 0, sizeof(obj)); rc = ANY_OBJECT_Unmarshal(&obj, buffer, size, true); - pAssert(rc == TPM_RC_SUCCESS); + if (rc != TPM_RC_SUCCESS) { + TPMLIB_LogTPM2Error("USER_NVRAM: Failed to unmarshal ANY_OBJECT: 0x%08x\n", + rc); + return rc; + } // convert the OBJECT into a buffer to copy into NVRAM marshalledObjectSize = NvObjectToBuffer(&obj, objBuffer, sizeof(objBuffer)); diff --git a/src/tpm2/RuntimeAlgorithm.c b/src/tpm2/RuntimeAlgorithm.c index f7ab2ee7c..6af9f4c93 100644 --- a/src/tpm2/RuntimeAlgorithm.c +++ b/src/tpm2/RuntimeAlgorithm.c @@ -514,7 +514,7 @@ RuntimeAlgorithmSwitchProfile(struct RuntimeAlgorithm *RuntimeAlgorithm, &stateFormatLevel, maxStateFormatLevel); if (retVal != TPM_RC_SUCCESS) { RuntimeAlgorithmSetProfile(RuntimeAlgorithm, *oldProfile, - &stateFormatLevel, maxStateFormatLevel); + &stateFormatLevel, ~0); *oldProfile = NULL; } return retVal; diff --git a/src/tpm2/RuntimeAttributes.c b/src/tpm2/RuntimeAttributes.c index e2e5b8ad1..a50f0fd12 100644 --- a/src/tpm2/RuntimeAttributes.c +++ b/src/tpm2/RuntimeAttributes.c @@ -185,7 +185,7 @@ RuntimeAttributesSwitchProfile(struct RuntimeAttributes *RuntimeAttributes, &stateFormatLevel, maxStateFormatLevel); if (retVal != TPM_RC_SUCCESS) { RuntimeAttributesSetProfile(RuntimeAttributes, *oldProfile, - &stateFormatLevel, maxStateFormatLevel); + &stateFormatLevel, ~0); *oldProfile = NULL; } return retVal; diff --git a/src/tpm2/RuntimeCommands.c b/src/tpm2/RuntimeCommands.c index 3edd31f57..cc2b29639 100644 --- a/src/tpm2/RuntimeCommands.c +++ b/src/tpm2/RuntimeCommands.c @@ -394,7 +394,7 @@ RuntimeCommandsSwitchProfile(struct RuntimeCommands *RuntimeCommands, &stateFormatLevel, maxStateFormatLevel); if (retVal != TPM_RC_SUCCESS) { RuntimeCommandsSetProfile(RuntimeCommands, *oldProfile, - &stateFormatLevel, maxStateFormatLevel); + &stateFormatLevel, ~0); *oldProfile = NULL; } return retVal; @@ -490,7 +490,7 @@ RuntimeCommandsGetArraySize(struct RuntimeCommands *RuntimeCommands) /* search for byte where command with highest code is enabled */ for (i = sizeof(RuntimeCommands->enabledCommandsByIdx) - 1; - i >= 0; + (ssize_t)i >= 0; i--) { if (RuntimeCommands->enabledCommandsByIdx[i]) return i + 1; diff --git a/src/tpm2/RuntimeProfile.c b/src/tpm2/RuntimeProfile.c index 59c99e98c..23a5c20e0 100644 --- a/src/tpm2/RuntimeProfile.c +++ b/src/tpm2/RuntimeProfile.c @@ -479,6 +479,9 @@ GetParametersFromJSON(const char *jsonProfile, return TPM_RC_SUCCESS; } + if (strlen(jsonProfile) > MAX_PROFILE_SIZE) + return TPM_RC_SIZE; + retVal = RuntimeProfileCheckJSON(jsonProfile); if (retVal != TPM_RC_SUCCESS) return retVal; diff --git a/src/tpm2/RuntimeProfile_fp.h b/src/tpm2/RuntimeProfile_fp.h index 37d6cae9d..a72ea947a 100644 --- a/src/tpm2/RuntimeProfile_fp.h +++ b/src/tpm2/RuntimeProfile_fp.h @@ -46,6 +46,8 @@ #include "RuntimeCommands_fp.h" #include "RuntimeAttributes_fp.h" +#define MAX_PROFILE_SIZE (32 * 1024) + struct RuntimeProfile { struct RuntimeAlgorithm RuntimeAlgorithm; struct RuntimeCommands RuntimeCommands; diff --git a/src/tpm2/Unmarshal.c b/src/tpm2/Unmarshal.c index e2aa0215b..6a575f083 100644 --- a/src/tpm2/Unmarshal.c +++ b/src/tpm2/Unmarshal.c @@ -47,7 +47,7 @@ TPM_RC UINT8_Unmarshal(UINT8 *target, BYTE **buffer, INT32 *size) { - if ((UINT32)*size < sizeof(UINT8)) { + if (*size < 0 || (UINT32)*size < sizeof(UINT8)) { return TPM_RC_INSUFFICIENT; } *target = (*buffer)[0]; @@ -65,7 +65,7 @@ INT8_Unmarshal(INT8 *target, BYTE **buffer, INT32 *size) TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size) { - if ((UINT32)*size < sizeof(UINT16)) { + if (*size < 0 || (UINT32)*size < sizeof(UINT16)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT16)((*buffer)[0]) << 8) | @@ -78,7 +78,7 @@ UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size) TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size) { - if ((UINT32)*size < sizeof(UINT32)) { + if (*size < 0 || (UINT32)*size < sizeof(UINT32)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT32)((*buffer)[0]) << 24) | @@ -93,7 +93,7 @@ UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size) TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size) { - if ((UINT32)*size < sizeof(UINT64)) { + if (*size < 0 || (UINT32)*size < sizeof(UINT64)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT64)((*buffer)[0]) << 56) | @@ -114,7 +114,7 @@ Array_Unmarshal(BYTE *targetBuffer, UINT16 targetSize, BYTE **buffer, INT32 *siz { TPM_RC rc = TPM_RC_SUCCESS; - if (targetSize > *size) { + if (*size < 0 || targetSize > (UINT32)*size) { rc = TPM_RC_INSUFFICIENT; } else { @@ -249,9 +249,10 @@ TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size) # endif // ECC_CURVE_448 if (*target != TPM_ECC_NONE && // libtpms added begin !CryptEccIsCurveRuntimeUsable(*target)) { - rc = TPM_RC_CURVE; + rc = TPM_RC_CURVE; } - if (!RuntimeAlgorithmKeySizeCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm, + if (rc == TPM_RC_SUCCESS && *target != TPM_ECC_NONE && + !RuntimeAlgorithmKeySizeCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm, TPM_ALG_ECC, CryptEccGetKeySizeForCurve(*target), *target,