From cfceb4e8b4922f3e17c9ad3e0088a98ce59e0255 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 17 Feb 2026 23:59:29 +0000 Subject: [PATCH 1/2] Improve get_ek_certs to handle indices --- examples/endorsement/get_ek_certs.c | 137 +++++++++++++++++++++++++++- src/tpm2_wrap.c | 4 +- wolftpm/tpm2.h | 6 ++ 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/examples/endorsement/get_ek_certs.c b/examples/endorsement/get_ek_certs.c index 7cd1b7ee..c4d2f916 100644 --- a/examples/endorsement/get_ek_certs.c +++ b/examples/endorsement/get_ek_certs.c @@ -57,6 +57,36 @@ static void usage(void) printf("./examples/endorsement/get_ek_certs\n"); } +#ifdef DEBUG_WOLFTPM +/* Decode and display NV attributes - only in debug mode */ +static void show_nv_attributes(TPMA_NV attr) +{ + printf(" Attributes:"); + if (attr & TPMA_NV_PPWRITE) printf(" PPWRITE"); + if (attr & TPMA_NV_OWNERWRITE) printf(" OWNERWRITE"); + if (attr & TPMA_NV_AUTHWRITE) printf(" AUTHWRITE"); + if (attr & TPMA_NV_POLICYWRITE) printf(" POLICYWRITE"); + if (attr & TPMA_NV_POLICY_DELETE) printf(" POLICY_DELETE"); + if (attr & TPMA_NV_WRITELOCKED) printf(" WRITELOCKED"); + if (attr & TPMA_NV_WRITEALL) printf(" WRITEALL"); + if (attr & TPMA_NV_WRITEDEFINE) printf(" WRITEDEFINE"); + if (attr & TPMA_NV_WRITE_STCLEAR) printf(" WRITE_STCLEAR"); + if (attr & TPMA_NV_GLOBALLOCK) printf(" GLOBALLOCK"); + if (attr & TPMA_NV_PPREAD) printf(" PPREAD"); + if (attr & TPMA_NV_OWNERREAD) printf(" OWNERREAD"); + if (attr & TPMA_NV_AUTHREAD) printf(" AUTHREAD"); + if (attr & TPMA_NV_POLICYREAD) printf(" POLICYREAD"); + if (attr & TPMA_NV_NO_DA) printf(" NO_DA"); + if (attr & TPMA_NV_ORDERLY) printf(" ORDERLY"); + if (attr & TPMA_NV_CLEAR_STCLEAR) printf(" CLEAR_STCLEAR"); + if (attr & TPMA_NV_READLOCKED) printf(" READLOCKED"); + if (attr & TPMA_NV_WRITTEN) printf(" WRITTEN"); + if (attr & TPMA_NV_PLATFORMCREATE) printf(" PLATFORMCREATE"); + if (attr & TPMA_NV_READ_STCLEAR) printf(" READ_STCLEAR"); + printf("\n"); +} +#endif + static void dump_hex_bytes(const byte* buf, word32 sz) { word32 i; @@ -237,7 +267,112 @@ int TPM2_EndorsementCert_Example(void* userCtx, int argc, char *argv[]) /* Get Endorsement Public Key template using NV index */ rc = wolfTPM2_GetKeyTemplate_EKIndex(nvIndex, &publicTemplate); if (rc != 0) { - printf("EK Index 0x%08x not valid\n", nvIndex); + const char* indexType = "Unknown"; + word32 offset = nvIndex - TPM_20_TCG_NV_SPACE; + + /* Identify the type of NV index based on offset */ + if (nvIndex < TPM_20_TCG_NV_SPACE) { + indexType = "Non-TCG (below TCG NV space)"; + } + else if (offset >= 0x2 && offset <= 0xC) { + indexType = "EK Low Range"; + if (offset == 0x2) indexType = "EK Low Range (RSA 2048 Cert)"; + else if (offset == 0x3) indexType = "EK Low Range (RSA 2048 Nonce)"; + else if (offset == 0x4) indexType = "EK Low Range (RSA 2048 Template)"; + else if (offset == 0xA) indexType = "EK Low Range (ECC P256 Cert)"; + else if (offset == 0xB) indexType = "EK Low Range (ECC P256 Nonce)"; + else if (offset == 0xC) indexType = "EK Low Range (ECC P256 Template)"; + } + else if (offset >= 0x12 && offset < 0x100) { + indexType = "EK High Range"; + if (offset == 0x12) indexType = "EK High Range (RSA 2048 Cert)"; + else if (offset == 0x14) indexType = "EK High Range (ECC P256 Cert)"; + else if (offset == 0x16) indexType = "EK High Range (ECC P384 Cert)"; + else if (offset == 0x18) indexType = "EK High Range (ECC P521 Cert)"; + else if (offset == 0x1A) indexType = "EK High Range (ECC SM2 Cert)"; + else if (offset == 0x1C) indexType = "EK High Range (RSA 3072 Cert)"; + else if (offset == 0x1E) indexType = "EK High Range (RSA 4096 Cert)"; + else if ((offset & 1) == 0) indexType = "EK High Range (Cert, even index)"; + else indexType = "EK High Range (Template, odd index)"; + } + else if (offset >= 0x100 && offset < 0x200) { + indexType = "EK Certificate Chain"; + } + else if (offset >= 0x7F01 && offset <= 0x7F04) { + indexType = "EK Policy Index"; + if (offset == 0x7F01) indexType = "EK Policy Index (SHA256)"; + else if (offset == 0x7F02) indexType = "EK Policy Index (SHA384)"; + else if (offset == 0x7F03) indexType = "EK Policy Index (SHA512)"; + else if (offset == 0x7F04) indexType = "EK Policy Index (SM3_256)"; + } + else if (nvIndex > TPM_20_TCG_NV_SPACE + 0x7FFF) { + indexType = "Vendor-specific (beyond TCG range)"; + } + + printf("NV Index 0x%08x: %s (not a recognized EK certificate index)\n", + nvIndex, indexType); + + /* Try to read the NV public info to show what it contains */ + rc = wolfTPM2_NVReadPublic(&dev, nvIndex, &nvPublic); + if (rc == 0) { + const char* hashName = TPM2_GetAlgName(nvPublic.nameAlg); + int isPolicyDigest = 0; + int showData = 0; + + #ifdef DEBUG_WOLFTPM + printf(" NV Size: %u bytes, Attributes: 0x%08x, Name Alg: %s\n", + nvPublic.dataSize, (unsigned int)nvPublic.attributes, hashName); + show_nv_attributes(nvPublic.attributes); + showData = 1; /* Always show data in debug mode */ + #else + printf(" NV Size: %u bytes, Name Alg: %s\n", + nvPublic.dataSize, hashName); + #endif + + /* Check if this looks like a policy digest based on size and hash */ + if ((nvPublic.dataSize == 32 && nvPublic.nameAlg == TPM_ALG_SHA256) || + (nvPublic.dataSize == 48 && nvPublic.nameAlg == TPM_ALG_SHA384) || + (nvPublic.dataSize == 64 && nvPublic.nameAlg == TPM_ALG_SHA512) || + (nvPublic.dataSize == 32 && nvPublic.nameAlg == TPM_ALG_SM3_256)) { + printf(" Type: Policy digest (%s hash)\n", hashName); + isPolicyDigest = 1; + showData = 1; /* Always show policy digests */ + } + else if (nvPublic.dataSize > 100) { + printf(" Type: Certificate or template\n"); + } + else if (nvPublic.dataSize > 32) { + printf(" Type: Data (%u bytes)\n", nvPublic.dataSize); + } + else { + printf(" Type: Small data (%u bytes)\n", nvPublic.dataSize); + #ifdef DEBUG_WOLFTPM + showData = 1; + #endif + } + + /* Read and display data if appropriate */ + if (showData && nvPublic.dataSize > 0) { + certSz = nvPublic.dataSize; + if (certSz > sizeof(certBuf)) { + certSz = sizeof(certBuf); + } + + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, certBuf, &certSz, 0); + if (rc == 0) { + if (nvPublic.dataSize <= 32 || isPolicyDigest) { + printf(" Data (%u bytes):\n", certSz); + dump_hex_bytes(certBuf, certSz); + } + else { + printf(" First 32 bytes:\n"); + dump_hex_bytes(certBuf, (certSz > 32) ? 32 : certSz); + } + } + } + } + + rc = 0; /* Reset error code to continue processing */ continue; } diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 24880a59..15ea907f 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -6446,9 +6446,9 @@ int wolfTPM2_GetKeyTemplate_EKIndex(word32 nvIndex, uint32_t keyBits = 0; int highRange = 0; - /* validate index is in NV EK range */ + /* validate index is in TCG NV space range (0x01C00000 - 0x01C07FFF) */ if (nvIndex < TPM_20_TCG_NV_SPACE || - nvIndex > TPM_20_TCG_NV_SPACE + 0x1FF) { + nvIndex > TPM_20_TCG_NV_SPACE + 0x7FFF) { return BAD_FUNC_ARG; } diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index dfd22115..ae506a2b 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -1708,6 +1708,12 @@ typedef struct TPM2_AUTH_SESSION { /* EK Certificate Chains (0x100 - 0x1FF) - Not common */ #define TPM2_NV_EK_CHAIN (TPM_20_TCG_NV_SPACE + 0x100) +/* EK Policy Indices for PolicyAuthorizeNV (0x7F01 - 0x7F04) */ +#define TPM2_NV_EK_POLICY_SHA256 (TPM_20_TCG_NV_SPACE + 0x7F01) +#define TPM2_NV_EK_POLICY_SHA384 (TPM_20_TCG_NV_SPACE + 0x7F02) +#define TPM2_NV_EK_POLICY_SHA512 (TPM_20_TCG_NV_SPACE + 0x7F03) +#define TPM2_NV_EK_POLICY_SM3_256 (TPM_20_TCG_NV_SPACE + 0x7F04) + /* Predetermined TPM 2.0 Endorsement policy auth templates */ /* SHA256 (Low Range) */ static const BYTE TPM_20_EK_AUTH_POLICY[] = { From b7e0bf6c2afaba96132dcd80642fbd8ea17bada5 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 19 Feb 2026 13:59:36 -0800 Subject: [PATCH 2/2] Peer review fixes --- examples/endorsement/get_ek_certs.c | 79 ++++++++++++++++------------- src/tpm2_wrap.c | 12 ++++- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/examples/endorsement/get_ek_certs.c b/examples/endorsement/get_ek_certs.c index c4d2f916..0a11c796 100644 --- a/examples/endorsement/get_ek_certs.c +++ b/examples/endorsement/get_ek_certs.c @@ -259,7 +259,7 @@ int TPM2_EndorsementCert_Example(void* userCtx, int argc, char *argv[]) for (nvIdx=0; nvIdx<(int)handles.count; nvIdx++) { nvIndex = handles.handle[nvIdx]; - XMEMSET(&nv, 0, sizeof(nv)); /* Must reset the NV for each read */ + XMEMSET(&nv, 0, sizeof(nv)); /* Reset NV handle for each index */ XMEMSET(certBuf, 0, sizeof(certBuf)); printf("TCG Handle 0x%x\n", nvIndex); @@ -268,45 +268,54 @@ int TPM2_EndorsementCert_Example(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_GetKeyTemplate_EKIndex(nvIndex, &publicTemplate); if (rc != 0) { const char* indexType = "Unknown"; - word32 offset = nvIndex - TPM_20_TCG_NV_SPACE; + word32 offset; /* Identify the type of NV index based on offset */ if (nvIndex < TPM_20_TCG_NV_SPACE) { indexType = "Non-TCG (below TCG NV space)"; } - else if (offset >= 0x2 && offset <= 0xC) { - indexType = "EK Low Range"; - if (offset == 0x2) indexType = "EK Low Range (RSA 2048 Cert)"; - else if (offset == 0x3) indexType = "EK Low Range (RSA 2048 Nonce)"; - else if (offset == 0x4) indexType = "EK Low Range (RSA 2048 Template)"; - else if (offset == 0xA) indexType = "EK Low Range (ECC P256 Cert)"; - else if (offset == 0xB) indexType = "EK Low Range (ECC P256 Nonce)"; - else if (offset == 0xC) indexType = "EK Low Range (ECC P256 Template)"; - } - else if (offset >= 0x12 && offset < 0x100) { - indexType = "EK High Range"; - if (offset == 0x12) indexType = "EK High Range (RSA 2048 Cert)"; - else if (offset == 0x14) indexType = "EK High Range (ECC P256 Cert)"; - else if (offset == 0x16) indexType = "EK High Range (ECC P384 Cert)"; - else if (offset == 0x18) indexType = "EK High Range (ECC P521 Cert)"; - else if (offset == 0x1A) indexType = "EK High Range (ECC SM2 Cert)"; - else if (offset == 0x1C) indexType = "EK High Range (RSA 3072 Cert)"; - else if (offset == 0x1E) indexType = "EK High Range (RSA 4096 Cert)"; - else if ((offset & 1) == 0) indexType = "EK High Range (Cert, even index)"; - else indexType = "EK High Range (Template, odd index)"; - } - else if (offset >= 0x100 && offset < 0x200) { - indexType = "EK Certificate Chain"; - } - else if (offset >= 0x7F01 && offset <= 0x7F04) { - indexType = "EK Policy Index"; - if (offset == 0x7F01) indexType = "EK Policy Index (SHA256)"; - else if (offset == 0x7F02) indexType = "EK Policy Index (SHA384)"; - else if (offset == 0x7F03) indexType = "EK Policy Index (SHA512)"; - else if (offset == 0x7F04) indexType = "EK Policy Index (SM3_256)"; - } - else if (nvIndex > TPM_20_TCG_NV_SPACE + 0x7FFF) { - indexType = "Vendor-specific (beyond TCG range)"; + else { + offset = nvIndex - TPM_20_TCG_NV_SPACE; + + if (offset >= 0x2 && offset <= 0xC) { + indexType = "EK Low Range"; + if (offset == 0x2) indexType = "EK Low Range (RSA 2048 Cert)"; + else if (offset == 0x3) indexType = "EK Low Range (RSA 2048 Nonce)"; + else if (offset == 0x4) indexType = "EK Low Range (RSA 2048 Template)"; + else if (offset == 0xA) indexType = "EK Low Range (ECC P256 Cert)"; + else if (offset == 0xB) indexType = "EK Low Range (ECC P256 Nonce)"; + else if (offset == 0xC) indexType = "EK Low Range (ECC P256 Template)"; + } + else if (offset >= 0x12 && offset < 0x100) { + indexType = "EK High Range"; + if (offset == 0x12) indexType = "EK High Range (RSA 2048 Cert)"; + else if (offset == 0x14) indexType = "EK High Range (ECC P256 Cert)"; + else if (offset == 0x16) indexType = "EK High Range (ECC P384 Cert)"; + else if (offset == 0x18) indexType = "EK High Range (ECC P521 Cert)"; + else if (offset == 0x1A) indexType = "EK High Range (ECC SM2 Cert)"; + else if (offset == 0x1C) indexType = "EK High Range (RSA 3072 Cert)"; + else if (offset == 0x1E) indexType = "EK High Range (RSA 4096 Cert)"; + else if ((offset & 1) == 0) indexType = "EK High Range (Cert, even index)"; + else indexType = "EK High Range (Template, odd index)"; + } + else if (offset >= 0x100 && offset < 0x200) { + indexType = "EK Certificate Chain"; + } + else if (offset == (TPM2_NV_EK_POLICY_SHA256 - TPM_20_TCG_NV_SPACE)) { + indexType = "EK Policy Index (SHA256)"; + } + else if (offset == (TPM2_NV_EK_POLICY_SHA384 - TPM_20_TCG_NV_SPACE)) { + indexType = "EK Policy Index (SHA384)"; + } + else if (offset == (TPM2_NV_EK_POLICY_SHA512 - TPM_20_TCG_NV_SPACE)) { + indexType = "EK Policy Index (SHA512)"; + } + else if (offset == (TPM2_NV_EK_POLICY_SM3_256 - TPM_20_TCG_NV_SPACE)) { + indexType = "EK Policy Index (SM3_256)"; + } + else if (nvIndex > TPM_20_TCG_NV_SPACE + 0x7FFF) { + indexType = "Vendor-specific (beyond TCG range)"; + } } printf("NV Index 0x%08x: %s (not a recognized EK certificate index)\n", diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 15ea907f..d23facd2 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -6445,13 +6445,23 @@ int wolfTPM2_GetKeyTemplate_EKIndex(word32 nvIndex, TPM_ECC_CURVE curveID = TPM_ECC_NONE; uint32_t keyBits = 0; int highRange = 0; + word32 offset; - /* validate index is in TCG NV space range (0x01C00000 - 0x01C07FFF) */ + /* Validate index is in TCG NV space */ if (nvIndex < TPM_20_TCG_NV_SPACE || nvIndex > TPM_20_TCG_NV_SPACE + 0x7FFF) { return BAD_FUNC_ARG; } + offset = nvIndex - TPM_20_TCG_NV_SPACE; + + /* Reject indices in dead zones that cannot produce valid templates: + * - Between High Range (0x1FF) and Policy Indices (0x7F01) + * - After Policy Indices (0x7F04) */ + if ((offset > 0x1FF && offset < 0x7F01) || offset > 0x7F04) { + return BAD_FUNC_ARG; + } + /* determine if low or high range */ if (nvIndex >= TPM2_NV_EK_RSA2048) { highRange = 1;