mirror of https://github.com/wolfSSL/wolfBoot.git
F-4973: clamp TPM-supplied nvPublic.dataSize before NV read-back in rot.c
The TPM-bus-supplied UINT16 nvPublic.dataSize was assigned to digestSz and forwarded to wolfTPM2_NVReadAuth as the read byte count with no bound check. wolfTPM2_NVReadAuthPolicy uses that count as the XMEMCPY length into the caller's buffer with no separate capacity argument, so a malicious/emulated TPM (or a pre-existing NV index larger than the hash) reporting dataSize > 64 overflows the 64-byte digest[WC_MAX_DIGEST_SIZE] stack buffer. Clamp digestSz to sizeof(digest) before the read. Stored values are key-hash digests (<= WC_MAX_DIGEST_SIZE), so the clamp never truncates valid data. Add a unit-rot-auth case driving nvPublic.dataSize=1000 through the existing mocked harness, asserting the requested read count is clamped to the buffer.pull/791/head
parent
03f5193dc2
commit
eaa6e4201a
|
|
@ -161,6 +161,12 @@ static int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvBase
|
|||
}
|
||||
if (rc == 0) {
|
||||
digestSz = nvPublic.dataSize;
|
||||
/* dataSize is supplied by the TPM over the bus; clamp it to the
|
||||
* digest buffer so a malicious/emulated TPM (or a pre-existing NV
|
||||
* index larger than the hash) cannot overflow digest[] during the
|
||||
* read-back below, which uses digestSz as the copy count. */
|
||||
if (digestSz > (int)sizeof(digest))
|
||||
digestSz = (int)sizeof(digest);
|
||||
|
||||
/* Read access */
|
||||
printf("Reading NV 0x%x public key hash\n", nv.handle.hndl);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
static uint8_t test_pubkey[32];
|
||||
static int symmetric_corrupted;
|
||||
static uint32_t mock_nv_datasize = 32;
|
||||
static uint32_t mock_nvread_reqsz;
|
||||
|
||||
#define TPM2_IoCb NULL
|
||||
#define XSTRTOL strtol
|
||||
|
|
@ -86,7 +88,7 @@ int wolfTPM2_NVReadPublic(WOLFTPM2_DEV* dev, TPM_HANDLE nvIndex,
|
|||
(void)dev;
|
||||
(void)nvIndex;
|
||||
memset(nvPublic, 0, sizeof(*nvPublic));
|
||||
nvPublic->dataSize = 32;
|
||||
nvPublic->dataSize = (UINT16)mock_nv_datasize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +104,14 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, TPM_HANDLE nvIndex,
|
|||
memset(&zero_sym, 0, sizeof(zero_sym));
|
||||
symmetric_corrupted =
|
||||
memcmp(&nv->handle.symmetric, &zero_sym, sizeof(zero_sym)) != 0;
|
||||
memset(dataBuf, 0xA5, *dataSz);
|
||||
/* Record the byte count the caller asked us to copy. The real
|
||||
* wolfTPM2_NVReadAuth uses this as the XMEMCPY count into dataBuf with no
|
||||
* separate capacity argument, so the caller must clamp it to its buffer.
|
||||
* Cap the actual write at WC_MAX_DIGEST_SIZE so this harness never itself
|
||||
* overflows the caller's digest[] buffer regardless of the requested size. */
|
||||
mock_nvread_reqsz = *dataSz;
|
||||
memset(dataBuf, 0xA5,
|
||||
*dataSz > WC_MAX_DIGEST_SIZE ? WC_MAX_DIGEST_SIZE : *dataSz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -234,6 +243,31 @@ START_TEST(test_rot_rejects_oversized_auth)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_rot_clamps_nv_datasize)
|
||||
{
|
||||
char auth[] = "test-auth";
|
||||
int rc;
|
||||
|
||||
/* Emulate a malicious/emulated TPM (or a pre-existing NV index) whose
|
||||
* reported dataSize exceeds the 64-byte digest[] read buffer. The value
|
||||
* must be clamped before being used as the read byte count, otherwise
|
||||
* wolfTPM2_NVReadAuth overflows digest[WC_MAX_DIGEST_SIZE]. */
|
||||
memset(test_pubkey, 0x11, sizeof(test_pubkey));
|
||||
symmetric_corrupted = 0;
|
||||
mock_nvread_reqsz = 0;
|
||||
mock_nv_datasize = 1000;
|
||||
|
||||
rc = TPM2_Boot_SecureROT_Example(TPM_RH_PLATFORM,
|
||||
WOLFBOOT_TPM_KEYSTORE_NV_BASE, WC_HASH_TYPE_SHA256, 0, 0, auth,
|
||||
(int)strlen(auth));
|
||||
|
||||
mock_nv_datasize = 32; /* restore default for other tests */
|
||||
|
||||
ck_assert_int_eq(rc, 0);
|
||||
ck_assert_int_le(mock_nvread_reqsz, (uint32_t)WC_MAX_DIGEST_SIZE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite* rot_auth_suite(void)
|
||||
{
|
||||
Suite* s;
|
||||
|
|
@ -242,6 +276,7 @@ static Suite* rot_auth_suite(void)
|
|||
s = suite_create("rot_auth");
|
||||
tc = tcase_create("auth_validation");
|
||||
tcase_add_test(tc, test_rot_rejects_oversized_auth);
|
||||
tcase_add_test(tc, test_rot_clamps_nv_datasize);
|
||||
suite_add_tcase(s, tc);
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue