mirror of https://github.com/wolfSSL/wolfBoot.git
tpm: DevId identity allow to use precomputed auth values
Allow to either use a master different that the sample one or to directly use the pre-computed per-device auth values for EH and AIK. Using the per-device value is preferred as it doesn't expose the auth value of the sibling devices in the same fleet.pull/803/head
parent
61fd552526
commit
801ae8f1ca
36
docs/TPM.md
36
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
43
src/tpm.c
43
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);
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
Loading…
Reference in New Issue