mirror of https://github.com/wolfSSL/wolfBoot.git
F-4644: validate NS pointers in TPM CSME_NSE_API veneers with cmse_check_address_range
The eleven CSME_NSE_API TPM veneers in src/tpm.c are cmse_nonsecure_entry gateways when built with TZEN=1 (e.g. config/examples/stm32h5-tz-tpm.config, which exposes them to the non-secure STM32H5 test app). Each accepted a typed pointer from the non-secure caller and immediately used it as a dereference or memset/XMEMSET target on the Secure side -- memset(caps), memset(handles), memset(getTime), XMEMSET(quoteResult), and the in/out forwards to TPM2_GetCapability / TPM2_ParseAttest. Because Secure code can write Secure SRAM, a malicious non-secure caller could pass a Secure pointer and turn any of these veneers into a confused-deputy write primitive against Secure memory. Validate every non-secure-supplied pointer with cmse_check_address_range (CMSE_NONSECURE, plus CMSE_MPU_READWRITE for write targets) before the first use, returning BAD_FUNC_ARG (or NULL for the string helpers) when the range is not accessible from the non-secure world. The check is wrapped in WOLFBOOT_TPM_NS_RW/WOLFBOOT_TPM_NS_R, guarded by __ARM_FEATURE_CMSE == 3U so non-CMSE builds (where there is no security boundary) collapse to a plain non-NULL pass-through. Buffer sizes use the caller-provided/known capacities (name_sz, error_sz, *certSz, PCR digest size). Verified by building wolfboot.elf with the stm32h5-tz-tpm config (-mcmse); the bug itself is a TrustZone Secure/Non-secure partitioning issue that cannot be exercised on the host unit-test build.pull/788/head
parent
d175c819cd
commit
091b4eabbe
66
src/tpm.c
66
src/tpm.c
|
|
@ -1230,14 +1230,39 @@ static int wolfRNG_GetSeedCB(OS_Seed* os, uint8_t* seed, uint32_t sz)
|
|||
|
||||
|
||||
/* API's that are callable from non-secure code */
|
||||
|
||||
/* Validate that a buffer supplied by the non-secure caller is fully
|
||||
* accessible from the non-secure world before the secure side dereferences
|
||||
* it. Without this check a non-secure caller could pass a pointer into Secure
|
||||
* SRAM and turn these veneers into a confused-deputy write primitive against
|
||||
* Secure memory. Outside of a CMSE secure build there is no security boundary,
|
||||
* so the checks collapse to a simple non-NULL pass-through. */
|
||||
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
#include <arm_cmse.h>
|
||||
#define WOLFBOOT_TPM_NS_RW(p, sz) \
|
||||
cmse_check_address_range((void*)(p), (size_t)(sz), \
|
||||
CMSE_NONSECURE | CMSE_MPU_READWRITE)
|
||||
#define WOLFBOOT_TPM_NS_R(p, sz) \
|
||||
cmse_check_address_range((void*)(p), (size_t)(sz), CMSE_NONSECURE)
|
||||
#else
|
||||
#define WOLFBOOT_TPM_NS_RW(p, sz) ((void*)(p))
|
||||
#define WOLFBOOT_TPM_NS_R(p, sz) ((void*)(p))
|
||||
#endif
|
||||
|
||||
int CSME_NSE_API wolfBoot_tpm2_caps(WOLFTPM2_CAPS* caps)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_RW(caps, sizeof(*caps)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
memset(caps, 0, sizeof(*caps));
|
||||
return wolfTPM2_GetCapabilities(&wolftpm_dev, caps);
|
||||
}
|
||||
|
||||
int CSME_NSE_API wolfBoot_tpm2_get_handles(TPM_HANDLE handle, TPML_HANDLE* handles)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_RW(handles, sizeof(*handles)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
memset(handles, 0, sizeof(*handles));
|
||||
return wolfTPM2_GetHandles(handle, handles);
|
||||
}
|
||||
|
|
@ -1249,6 +1274,9 @@ const char* CSME_NSE_API wolfBoot_tpm2_get_alg_name(TPM_ALG_ID alg,
|
|||
if (name == NULL || name_sz <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(name, name_sz) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
s_name = TPM2_GetAlgName(alg);
|
||||
if (s_name != NULL && name != NULL && name_sz > 0) {
|
||||
strncpy(name, s_name, name_sz - 1);
|
||||
|
|
@ -1267,6 +1295,9 @@ const char* CSME_NSE_API wolfBoot_tpm2_get_rc_string(int rc, char* error, int er
|
|||
if (error == NULL || error_sz <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(error, error_sz) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
s_error = TPM2_GetRCString(rc);
|
||||
if (s_error != NULL && error != NULL && error_sz > 0) {
|
||||
strncpy(error, s_error, error_sz - 1);
|
||||
|
|
@ -1281,17 +1312,32 @@ const char* CSME_NSE_API wolfBoot_tpm2_get_rc_string(int rc, char* error, int er
|
|||
|
||||
int CSME_NSE_API wolfBoot_tpm2_get_capability(GetCapability_In* in, GetCapability_Out* out)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_R(in, sizeof(*in)) == NULL ||
|
||||
WOLFBOOT_TPM_NS_RW(out, sizeof(*out)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
return (int)TPM2_GetCapability(in, out);
|
||||
}
|
||||
|
||||
int CSME_NSE_API wolfBoot_tpm2_read_pcr(uint8_t pcrIndex, uint8_t* digest, int* digestSz)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_RW(digest,
|
||||
TPM2_GetHashDigestSize(WOLFBOOT_TPM_PCR_ALG)) == NULL ||
|
||||
WOLFBOOT_TPM_NS_RW(digestSz, sizeof(*digestSz)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
return wolfTPM2_ReadPCR(&wolftpm_dev, pcrIndex, WOLFBOOT_TPM_PCR_ALG,
|
||||
digest, digestSz);
|
||||
}
|
||||
|
||||
int CSME_NSE_API wolfBoot_tpm2_read_cert(uint32_t handle, uint8_t* cert, uint32_t* certSz)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_RW(certSz, sizeof(*certSz)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(cert, *certSz) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
wolfTPM2_SetAuthPassword(&wolftpm_dev, 0, NULL);
|
||||
return wolfTPM2_NVReadCert(&wolftpm_dev, handle, cert, certSz);
|
||||
}
|
||||
|
|
@ -1304,6 +1350,13 @@ int CSME_NSE_API wolfBoot_tpm2_get_aik(WOLFTPM2_KEY* aik,
|
|||
if (aik == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(aik, sizeof(*aik)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (masterPassword != NULL &&
|
||||
WOLFBOOT_TPM_NS_R(masterPassword, masterPasswordSz) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Load existing AIK and set auth */
|
||||
rc = wolfTPM2_ReadPublicKey(&wolftpm_dev, aik, TPM2_IAK_KEY_HANDLE);
|
||||
|
|
@ -1330,6 +1383,10 @@ int CSME_NSE_API wolfBoot_tpm2_get_timestamp(WOLFTPM2_KEY* aik, GetTime_Out* get
|
|||
if (aik == NULL || getTime == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(aik, sizeof(*aik)) == NULL ||
|
||||
WOLFBOOT_TPM_NS_RW(getTime, sizeof(*getTime)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
memset(getTime, 0, sizeof(*getTime));
|
||||
memset(&eh_handle, 0, sizeof(eh_handle));
|
||||
|
|
@ -1358,6 +1415,10 @@ int CSME_NSE_API wolfBoot_tpm2_get_timestamp(WOLFTPM2_KEY* aik, GetTime_Out* get
|
|||
|
||||
int CSME_NSE_API wolfBoot_tpm2_parse_attest(const TPM2B_ATTEST* in, TPMS_ATTEST* out)
|
||||
{
|
||||
if (WOLFBOOT_TPM_NS_R(in, sizeof(*in)) == NULL ||
|
||||
WOLFBOOT_TPM_NS_RW(out, sizeof(*out)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
return TPM2_ParseAttest(in, out);
|
||||
}
|
||||
|
||||
|
|
@ -1372,6 +1433,11 @@ int CSME_NSE_API wolfBoot_tpm2_quote(WOLFTPM2_KEY* aik,
|
|||
quoteResult == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (WOLFBOOT_TPM_NS_RW(aik, sizeof(*aik)) == NULL ||
|
||||
WOLFBOOT_TPM_NS_R(pcrArray, pcrArraySz) == NULL ||
|
||||
WOLFBOOT_TPM_NS_RW(quoteResult, sizeof(*quoteResult)) == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* set auth for using the AIK */
|
||||
wolfTPM2_SetAuthHandle(&wolftpm_dev, 0, &aik->handle);
|
||||
|
|
|
|||
Loading…
Reference in New Issue