From 63bb85ae9d3b08423b2aa4741648dc23bf626c09 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 20 Mar 2024 10:30:09 -0700 Subject: [PATCH] Add support for pre-provisioned TPM using the "TPM 2.0 Keys for Device Identity and Attestation" specification. Build macro: `WOLFTPM_MFG_IDENTITY`. --- src/tpm2.c | 42 +++++++++++++---- src/tpm2_wrap.c | 112 ++++++++++++++++++++++++++++++++++++++++++++ wolftpm/tpm2_wrap.h | 20 ++++++++ 3 files changed, 164 insertions(+), 10 deletions(-) diff --git a/src/tpm2.c b/src/tpm2.c index 4628e5a..f6f5c05 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -5261,16 +5261,38 @@ TPM_RC TPM2_GetProductInfo(uint8_t* info, uint16_t size) { TPM_RC rc; TPM2_CTX* ctx = TPM2_GetActiveCtx(); - - TPM2_Packet packet; - TPM2_Packet_Init(ctx, &packet); - TPM2_Packet_AppendU32(&packet, 0x100); - TPM2_Packet_AppendU32(&packet, 3); - TPM2_Packet_AppendU32(&packet, 1); - TPM2_Packet_Finalize(&packet, TPM_ST_NO_SESSIONS, TPM_CC_GetCapability); - - rc = TPM2_SendCommand(ctx, &packet); - if (rc == TPM_RC_SUCCESS) memcpy(info, &packet.buf[25], size); + + if (ctx == NULL || info == NULL) + return BAD_FUNC_ARG; + + rc = TPM2_AcquireLock(ctx); + if (rc == TPM_RC_SUCCESS) { + TPM2_Packet packet; + TPM2_Packet_Init(ctx, &packet); + TPM2_Packet_AppendU32(&packet, TPM_CAP_VENDOR_PROPERTY); + TPM2_Packet_AppendU32(&packet, 3); /* cTPM_SUBCAP_VENDOR_GET_PRODUCT_INFO */ + TPM2_Packet_AppendU32(&packet, 1); /* only 1 property */ + TPM2_Packet_Finalize(&packet, TPM_ST_NO_SESSIONS, TPM_CC_GetCapability); + + /* send command */ + rc = TPM2_SendCommand(ctx, &packet); + if (rc == TPM_RC_SUCCESS) { + /* Product info is: + * Serial Number (7 bytes) + * Pad (1 byte) + * Product ID (PIN) (2 bytes) + * Master Product ID (MPIN) (2 bytes) + * Product Internal Revision (1 byte) + * Pad (3 bytes) + * Firmware kernel version (4 bytes) + */ + + /* start of product info starts at byte 26 */ + if (size > packet.size - 26) + size = packet.size - 26; + XMEMCPY(info, &packet.buf[25], size); + } + } return rc; } #endif /* WOLFTPM_ST33 || WOLFTPM_AUTODETECT */ diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 51fdeec..6921d29 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -4421,6 +4421,42 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, return rc; } +int wolfTPM2_NVReadCert(WOLFTPM2_DEV* dev, TPM_HANDLE handle, + uint8_t* buffer, uint32_t* len) +{ + int rc; + WOLFTPM2_NV nv; + TPMS_NV_PUBLIC nvPublic; + + XMEMSET(&nvPublic, 0, sizeof(nvPublic)); + XMEMSET(&nv, 0, sizeof(nv)); + + /* Get or check size of NV */ + rc = wolfTPM2_NVReadPublic(dev, handle, &nvPublic); + if (rc == 0) { + if (buffer == NULL) { + /* just return size */ + *len = nvPublic.dataSize; + return 0; + } + if (nvPublic.dataSize > *len) { + return BUFFER_E; + } + } + else { + #ifdef DEBUG_WOLFTPM + printf("NV public read of handle 0x%x failed %d: %s\n", + handle, rc, wolfTPM2_GetRCString(rc)); + #endif + return rc; + } + + /* Perform read of NV without auth password */ + nv.handle.hndl = handle; + rc = wolfTPM2_NVReadAuth(dev, &nv, handle, buffer, len, 0); + return rc; +} + /* older API kept for compatibility, recommend using wolfTPM2_NVReadAuth */ int wolfTPM2_NVRead(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, word32 nvIndex, byte* dataBuf, word32* pDataSz, word32 offset) @@ -7003,4 +7039,80 @@ int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, /* --- END Policy Support -- */ /******************************************************************************/ + + +/******************************************************************************/ +/* --- BEGIN Provisioned TPM Support -- */ +/******************************************************************************/ + +/* pre-provisioned IAK and IDevID key/cert from TPM vendor */ +#ifdef WOLFTPM_MFG_IDENTITY + +#ifdef TEST_SAMPLE +static const uint8_t* TPM2_IAK_SAMPLE_MASTER_PASSWORD = { + 0xFE, 0xEF, 0x8C, 0xDF, 0x1B, 0x77, 0xBD, 0x00, + 0x30, 0x58, 0x5E, 0x47, 0xB8, 0x21, 0x46, 0x0B +}; +#endif + +int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle, + uint8_t* masterPassword, uint16_t masterPasswordSz) +{ + int rc; + uint8_t serialNum[7]; + wc_HashAlg hash_ctx; + enum wc_HashType hashType = WC_HASH_TYPE_SHA256; + uint8_t digest[TPM_SHA256_DIGEST_SIZE]; + + /* Get TPM serial number */ + rc = TPM2_GetProductInfo(serialNum, (uint16_t)sizeof(serialNum)); + if (rc != 0) { + #ifdef DEBUG_WOLFTPM + printf("TPM2_GetProductInfo failed %d: %s\n", + rc, wolfTPM2_GetRCString(rc)); + #endif + return rc; + } + + /* Hash both values */ + rc = wc_HashInit(&hash_ctx, hashType); + if (rc == 0) { + rc = wc_HashUpdate(&hash_ctx, hashType, serialNum, sizeof(serialNum)); + if (rc == 0) + #ifdef TEST_SAMPLE + rc = wc_HashUpdate(&hash_ctx, hashType, + TPM2_IAK_SAMPLE_MASTER_PASSWORD, + sizeof(TPM2_IAK_SAMPLE_MASTER_PASSWORD)); + (void)masterPassword; + (void)masterPasswordSs; + #else + rc = wc_HashUpdate(&hash_ctx, hashType, + masterPassword, masterPasswordSz); + #endif + if (rc == 0) { + rc = wc_HashFinal(&hash_ctx, hashType, digest); + } + + wc_HashFree(&hash_ctx, hashType); + } + + /* Hash Final truncate to 16 bytes */ + /* Use 16-byte for auth when accessing key */ + handle->auth.size = 16; + XMEMCPY(handle->auth.buffer, &digest[16], 16); + + (void)dev; + + return rc; +} + +#endif /* WOLFTPM_MFG_IDENTITY */ + +/******************************************************************************/ +/* --- END Provisioned TPM Support -- */ +/******************************************************************************/ + + + + #endif /* !WOLFTPM2_NO_WRAPPER */ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 1fb3cc9..4f9cd78 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -1911,6 +1911,9 @@ WOLFTPM_API int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, WOLFTPM_API int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32* pDataSz, word32 offset); +WOLFTPM_API int wolfTPM2_NVReadCert(WOLFTPM2_DEV* dev, TPM_HANDLE handle, + uint8_t* buffer, uint32_t* len); + /*! \ingroup wolfTPM2_Wrappers \brief Increments an NV one-way counter @@ -3539,6 +3542,23 @@ WOLFTPM_API int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, const byte* policyRef, word32 policyRefSz); +/* pre-provisioned IAK and IDevID key/cert from TPM vendor */ +#ifdef WOLFTPM_MFG_IDENTITY + +/* Initial attestation key (IAK) and an initial device ID (IDevID) */ +/* Default is: ECDSA SECP384P1, SHA2-384 */ +#define TPM2_IAK_KEY_HANDLE 0x81080000 +#define TPM2_IAK_CERT_HANDLE 0x1C20100 + +#define TPM2_IDEVID_KEY_HANDLE 0x81080001 +#define TPM2_IDEVID_CERT_HANDLE 0x1C20101 + +WOLFTPM_API int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle, + uint8_t* masterPassword, uint16_t masterPasswordSz); + +#endif /* WOLFTPM_MFG_IDENTITY */ + + /* Internal API's */ WOLFTPM_LOCAL int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, int keyBits, long exponent,