Add support for pre-provisioned TPM using the "TPM 2.0 Keys for Device Identity and Attestation" specification. Build macro: `WOLFTPM_MFG_IDENTITY`.

pull/336/head
David Garske 2024-03-20 10:30:09 -07:00
parent c4880bee18
commit 63bb85ae9d
3 changed files with 164 additions and 10 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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,