diff --git a/docs/TPM.md b/docs/TPM.md index 94fd77f2..228b03f2 100644 --- a/docs/TPM.md +++ b/docs/TPM.md @@ -17,6 +17,42 @@ In wolfBoot we support TPM based root of trust, sealing/unsealing, cryptographic | `WOLFBOOT_TPM_SEAL=1` | `WOLFBOOT_TPM_SEAL` | Enables support for sealing/unsealing based on PCR policy signed externally. | | `WOLFBOOT_TPM_SEAL_NV_BASE=0x01400300` | `WOLFBOOT_TPM_SEAL_NV_BASE` | To override the default sealed blob storage location in the platform hierarchy. | | `WOLFBOOT_TPM_SEAL_AUTH=secret` | `WOLFBOOT_TPM_SEAL_AUTH` | Password for sealing/unsealing secrets, if omitted the PCR policy will be used | +| `WOLFBOOT_TPM_MFG_AUTH_DERIVE=1` | `WOLFBOOT_TPM_MFG_AUTH_DERIVE` | MFG identity: opt into on-device derive-from-master. The default is a precomputed per-device authValue (no master secret on device). Requires `WOLFTPM_MFG_IDENTITY`. | +| (header macro) | `WOLFBOOT_TPM_MFG_AIK_AUTH` / `WOLFBOOT_TPM_MFG_EH_AUTH` | Default (precomputed) mode: the 16-byte per-device AIK / EH authValues (placeholder `0xFF` default). | +| (header macro) | `WOLFBOOT_TPM_MFG_EH_MASTER` | Derive mode: override the endorsement-hierarchy master value (16-byte initializer list, sample default). | + +## TPM manufacturing identity (IAK / IDevID authValue) + +When `WOLFTPM_MFG_IDENTITY` is enabled, `wolfBoot_tpm2_get_aik()` and +`wolfBoot_tpm2_get_timestamp()` authorize the pre-provisioned ST33KTPM identity +keys. There are two ways to supply the required `authValue`: + +- **Precomputed mode (default, recommended).** The final **per-device** + `authValue` is set directly into the key handle; no master secret is present on + the device. Defaults to a `0xFF` placeholder (fails TPM auth until + provisioned). Per-device values are computed off-device at provisioning + (`SHA-256(CPSN || master)`, low 16 bytes) and baked in via + `WOLFBOOT_TPM_MFG_AIK_AUTH` / `WOLFBOOT_TPM_MFG_EH_AUTH`. When `WOLFBOOT_TPM_MFG_AUTH_DERIVE` + is not enabled, the `masterPassword` argument to `wolfBoot_tpm2_get_aik()` is + treated as an optional override for the final AIK `authValue` (not a master secret). + +- **Derive mode (`WOLFBOOT_TPM_MFG_AUTH_DERIVE`).** The `authValue` is computed + on-device as the low 16 bytes of `SHA-256(TPM serial || master)`. + The endorsement master defaults to a sample and is overridable with + `WOLFBOOT_TPM_MFG_EH_MASTER`; the AIK master is passed to + `wolfBoot_tpm2_get_aik()` (NULL = sample). Convenient, but the master is + **shared across the whole reel/batch** — extracting it + from one device's firmware lets an attacker derive the `authValue` for every + sibling device. + +The byte-array macros are header defaults (overridable via `-D` / `CFLAGS_EXTRA`); +they are not plain `options.mk` variables because brace initializers contain +commas. `WOLFTPM_MFG_IDENTITY` itself is supplied via `CFLAGS_EXTRA`. + +> Note: because precomputed mode is the default and ships a `0xFF` placeholder, a +> build that enables `WOLFTPM_MFG_IDENTITY` without provisioning the authValue (or +> selecting `WOLFBOOT_TPM_MFG_AUTH_DERIVE`) fails TPM auth by design. The test-app +> builds with `WOLFBOOT_TPM_MFG_AUTH_DERIVE` so it works on a sample TPM. ## Root of Trust (ROT) diff --git a/include/tpm.h b/include/tpm.h index 08cd1044..c1198288 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -60,6 +60,37 @@ int CSME_NSE_API wolfBoot_tpm2_read_pcr(uint8_t pcrIndex, uint8_t* digest, int* int CSME_NSE_API wolfBoot_tpm2_read_cert(uint32_t handle, uint8_t* cert, uint32_t* certSz); #ifdef WOLFTPM_MFG_IDENTITY + +/* MFG identity auth provisioning. + * Precomputed mode (default): the final per-device authValue is set directly, + * no master secret on the device. In this mode, wolfBoot_tpm2_get_aik() treats + * the masterPassword argument as an optional *authValue* override. + * Derive mode (WOLFBOOT_TPM_MFG_AUTH_DERIVE): authValue = low 16 bytes of + * SHA-256(TPM serial || master); the master is shared across the reel. + * For wolfBott_tpm2_get_aik() the master password is provided via the + * masterPassword argument (NULL = sample). */ +#ifdef WOLFBOOT_TPM_MFG_AUTH_DERIVE +/* EH master for derive mode (sample - override in production) */ +#ifndef WOLFBOOT_TPM_MFG_EH_MASTER +#define WOLFBOOT_TPM_MFG_EH_MASTER { \ + 0xDE, 0xEF, 0x8C, 0xDF, 0x1B, 0x77, 0xBD, 0x00, \ + 0x30, 0x58, 0x5E, 0x47, 0xB8, 0x21, 0x46, 0x0B } +#endif +#else +/* 16-byte per-device authValues. Placeholder defaults (all 0xFF) fail TPM auth + * until overwritten per-device by the provisioning tool. */ +#ifndef WOLFBOOT_TPM_MFG_AIK_AUTH +#define WOLFBOOT_TPM_MFG_AIK_AUTH { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +#endif +#ifndef WOLFBOOT_TPM_MFG_EH_AUTH +#define WOLFBOOT_TPM_MFG_EH_AUTH { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +#endif +#endif + int CSME_NSE_API wolfBoot_tpm2_get_aik(WOLFTPM2_KEY* aik, uint8_t* masterPassword, uint16_t masterPasswordSz); int CSME_NSE_API wolfBoot_tpm2_get_timestamp(WOLFTPM2_KEY* aik, GetTime_Out* getTime); diff --git a/options.mk b/options.mk index 37f676d7..b6b18a5a 100644 --- a/options.mk +++ b/options.mk @@ -58,6 +58,12 @@ ifeq ($(WOLFBOOT_TPM_KEYSTORE),1) endif endif +## TPM manufacturing identity: precomputed per-device authValue is the default +## (no master secret on device). Opt into on-device derive-from-master mode: +ifeq ($(WOLFBOOT_TPM_MFG_AUTH_DERIVE),1) + CFLAGS+=-D"WOLFBOOT_TPM_MFG_AUTH_DERIVE" +endif + ifeq ($(WOLFBOOT_ATTESTATION_IAK),1) CFLAGS+=-D"WOLFBOOT_ATTESTATION_IAK" endif diff --git a/src/tpm.c b/src/tpm.c index 6a11aad2..c4fcea4b 100644 --- a/src/tpm.c +++ b/src/tpm.c @@ -1363,11 +1363,26 @@ int CSME_NSE_API wolfBoot_tpm2_get_aik(WOLFTPM2_KEY* aik, /* Load existing AIK and set auth */ rc = wolfTPM2_ReadPublicKey(&wolftpm_dev, aik, TPM2_IAK_KEY_HANDLE); if (rc == 0) { - /* Custom should supply their own custom master password used during - * device provisioning. If using a sample TPM supply NULL to use the - * default password. */ +#ifdef WOLFBOOT_TPM_MFG_AUTH_DERIVE + /* Derives the authValue on-device from a master secret shared across the + * reel; the precomputed default is preferred. Supply NULL for + * masterPassword to use the sample default. */ rc = wolfTPM2_SetIdentityAuth(&wolftpm_dev, &aik->handle, masterPassword, masterPasswordSz); +#else + /* Precomputed (default): set the final per-device authValue directly (no + * master secret on device). Caller may override the default via + * masterPassword. */ + static const uint8_t aikAuth[] = WOLFBOOT_TPM_MFG_AIK_AUTH; + const uint8_t* auth = (masterPassword != NULL) ? masterPassword : aikAuth; + uint16_t authSz = (masterPassword != NULL) ? + masterPasswordSz : (uint16_t)sizeof(aikAuth); + if (authSz > (uint16_t)sizeof(aik->handle.auth.buffer)) { + return BAD_FUNC_ARG; + } + aik->handle.auth.size = authSz; + XMEMCPY(aik->handle.auth.buffer, auth, authSz); +#endif } return rc; } @@ -1376,11 +1391,13 @@ int CSME_NSE_API wolfBoot_tpm2_get_timestamp(WOLFTPM2_KEY* aik, GetTime_Out* get { int rc; WOLFTPM2_HANDLE eh_handle; - /* sample master password for EH */ - uint8_t Master_EH_AuthValue[] = { - 0xDE, 0xEF, 0x8C, 0xDF, 0x1B, 0x77, 0xBD, 0x00, - 0x30, 0x58, 0x5E, 0x47, 0xB8, 0x21, 0x46, 0x0B - }; +#ifdef WOLFBOOT_TPM_MFG_AUTH_DERIVE + /* EH master secret (shared across the reel) */ + uint8_t Master_EH_AuthValue[] = WOLFBOOT_TPM_MFG_EH_MASTER; +#else + /* final per-device EH authValue */ + static const uint8_t eh_auth[] = WOLFBOOT_TPM_MFG_EH_AUTH; +#endif if (aik == NULL || getTime == NULL) { return BAD_FUNC_ARG; @@ -1395,9 +1412,19 @@ int CSME_NSE_API wolfBoot_tpm2_get_timestamp(WOLFTPM2_KEY* aik, GetTime_Out* get eh_handle.hndl = TPM_RH_ENDORSEMENT; +#ifdef WOLFBOOT_TPM_MFG_AUTH_DERIVE /* Calculate EH auth value */ rc = wolfTPM2_SetIdentityAuth(&wolftpm_dev, &eh_handle, Master_EH_AuthValue, (uint16_t)sizeof(Master_EH_AuthValue)); +#else + /* Set EH authValue directly */ + if (sizeof(eh_auth) > sizeof(eh_handle.auth.buffer)) { + return BAD_FUNC_ARG; + } + eh_handle.auth.size = (uint16_t)sizeof(eh_auth); + XMEMCPY(eh_handle.auth.buffer, eh_auth, sizeof(eh_auth)); + rc = 0; +#endif if (rc == 0) { /* Set EH auth */ wolfTPM2_SetAuthHandle(&wolftpm_dev, 0, &eh_handle); diff --git a/tools/config.mk b/tools/config.mk index 98aa0dca..59d830f6 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -58,6 +58,7 @@ ifeq ($(ARCH),) MEASURED_BOOT?=0 WOLFBOOT_TPM_SEAL?=0 WOLFBOOT_TPM_KEYSTORE?=0 + WOLFBOOT_TPM_MFG_AUTH_DERIVE?=0 WOLFBOOT_ATTESTATION_IAK?=0 WOLFBOOT_ATTESTATION_TEST?=0 WOLFBOOT_UNIVERSAL_KEYSTORE?=0 @@ -106,6 +107,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO DISABLE_BACKUP WOLFBOOT_VERSION V NO_MPU ENCRYPT FLAGS_HOME FLAGS_INVERT \ SPMATH SPMATHALL RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA TZEN PSOC6_CRYPTO \ WOLFTPM WOLFBOOT_TPM_VERIFY MEASURED_BOOT WOLFBOOT_TPM_SEAL WOLFBOOT_TPM_KEYSTORE \ + WOLFBOOT_TPM_MFG_AUTH_DERIVE \ WOLFBOOT_ATTESTATION_IAK \ WOLFBOOT_ATTESTATION_TEST \ WOLFBOOT_UDS_UID_FALLBACK_FORTEST \