From cdde12c06ef25306e8b81cac06e0a160a9792571 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 11 Sep 2023 10:41:34 -0700 Subject: [PATCH] Fixes based on peer review. Add output of signed policy to file (append .sig). Tested successfully with multiple PCRs. In example unlock_disk extend PCR with random value after unseal to prevent unsealing after boot. --- docs/Signing.md | 1 + docs/TPM.md | 1 + include/tpm.h | 3 +++ src/tpm.c | 16 ++++++++-------- src/update_flash.c | 18 ++++++++++++++++++ tools/keytools/sign.c | 11 ++++++++++- tools/tpm/policy_create.c | 15 ++++++++------- 7 files changed, 49 insertions(+), 16 deletions(-) diff --git a/docs/Signing.md b/docs/Signing.md index 62e059cdd..85e6e4106 100644 --- a/docs/Signing.md +++ b/docs/Signing.md @@ -174,6 +174,7 @@ Provides a PCR mask and digest to be signed and included in the header. The sign By default the file should contain a 4-byte PCR mask and SHA2-256 PCR digest to be signed. If using `--manual-sign` then the file should contain the 4-byte PCR mask and signature. The PCR mask and signature will be included in the `HDR_POLICY_SIGNATURE` header tag. + A copy of the final signed policy (including 4 byte PCR mask) will be output to `[inputname].sig`. Note: This may require increasing the `IMAGE_HEADER_SIZE` as two signatures will be stored in the header. #### Three-steps signing using external provisioning tools diff --git a/docs/TPM.md b/docs/TPM.md index a69708511..7e74928b5 100644 --- a/docs/TPM.md +++ b/docs/TPM.md @@ -10,6 +10,7 @@ In wolfBoot we support TPM based root of trust, sealing/unsealing, cryptographic | `WOLFBOOT_TPM_VERIFY=1` | `WOLFBOOT_TPM_VERIFY` | Enables cryptographic offloading for RSA2048 and ECC256/384 to the TPM. | | `WOLFBOOT_TPM_KEYSTORE=1` | `WOLFBOOT_TPM_KEYSTORE` | Enables TPM based root of trust. NV Index must store a hash of the trusted public key. | | `WOLFBOOT_TPM_KEYSTORE_NV_BASE=0x` | `WOLFBOOT_TPM_KEYSTORE_NV_BASE=0x` | NV index in platform range 0x1400000 - 0x17FFFFF. | +| `WOLFBOOT_TPM_KEYSTORE_AUTH=secret` | `WOLFBOOT_TPM_KEYSTORE_AUTH` | Password for NV access | | `MEASURED_BOOT=1` | `WOLFBOOT_MEASURED_BOOT` | Enable measured boot. Extend PCR with wolfBoot hash. | | `MEASURED_PCR_A=16` | `WOLFBOOT_MEASURED_PCR_A=16` | The PCR index to use. See [docs/measured_boot.md](/docs/measured_boot.md). | | `WOLFBOOT_TPM_SEAL=1` | `WOLFBOOT_TPM_SEAL` | Enables support for sealing/unsealing based on PCR policy signed externally. | diff --git a/include/tpm.h b/include/tpm.h index e3ea9a56e..3a9bd929a 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -83,6 +83,9 @@ int wolfBoot_read_blob(uint32_t nvIndex, WOLFTPM2_KEYBLOB* blob, int wolfBoot_store_blob(TPMI_RH_NV_AUTH authHandle, uint32_t nvIndex, word32 nvAttributes, WOLFTPM2_KEYBLOB* blob, const uint8_t* auth, uint32_t authSz); + +uint32_t wolfBoot_tpm_pcrmask_sel(uint32_t pcrMask, uint8_t* pcrArray, + uint32_t pcrArraySz); #endif #ifdef WOLFBOOT_MEASURED_BOOT diff --git a/src/tpm.c b/src/tpm.c index 2c3068eb9..2d2c73d3d 100644 --- a/src/tpm.c +++ b/src/tpm.c @@ -467,20 +467,20 @@ int wolfBoot_get_pcr_active(uint8_t pcrAlg, uint32_t* pcrMask, uint8_t pcrMax) return rc; } -static void tpm_mask_sel_pcr(uint32_t pcrMask, uint8_t* pcrArray, - uint32_t* pcrArraySz) +uint32_t wolfBoot_tpm_pcrmask_sel(uint32_t pcrMask, uint8_t* pcrArray, + uint32_t pcrArraySz) { int i; - *pcrArraySz = 0; + uint32_t pcrArraySzAct = 0; for (i=0; i= PCR_SELECT_MAX*2) { + pcrArray[pcrArraySzAct++] = i; + if (pcrArraySzAct < pcrArraySz) { /* make sure we have room */ break; } } } + return pcrArraySzAct; } int wolfBoot_build_policy(uint8_t pcrAlg, uint32_t pcrMask, @@ -497,7 +497,7 @@ int wolfBoot_build_policy(uint8_t pcrAlg, uint32_t pcrMask, /* populate PCR selection array */ memset(pcrArray, 0, sizeof(pcrArray)); - tpm_mask_sel_pcr(pcrMask, pcrArray, &pcrArraySz); + pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask, pcrArray, sizeof(pcrArray)); /* Create a Policy PCR digest to sign externally */ memcpy(policy, (uint8_t*)&pcrMask, sizeof(pcrMask)); @@ -858,7 +858,7 @@ int wolfBoot_unseal_blob(struct wolfBoot_image* img, WOLFTPM2_KEYBLOB* seal_blob /* extract pcrMask and populate PCR selection array */ memcpy(&pcrMask, hdr, sizeof(pcrMask)); memset(pcrArray, 0, sizeof(pcrArray)); - tpm_mask_sel_pcr(pcrMask, pcrArray, &pcrArraySz); + pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask, pcrArray, sizeof(pcrArray)); /* skip to signature */ hdr += sizeof(pcrMask); diff --git a/src/update_flash.c b/src/update_flash.c index 67dbfcbda..104715c2c 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -646,6 +646,24 @@ int wolfBoot_unlock_disk(void) wolfBoot_printf("unlock disk failed! %d (%s)\n", ret, wolfTPM2_GetRCString(ret)); } + + /* Extend a PCR from the mask to prevent future unsealing */ + { + uint32_t pcrMask; + uint32_t pcrArraySz; + uint8_t pcrArray[1]; + /* random value to extend the first PCR mask */ + const uint8_t digest[WOLFBOOT_TPM_PCR_DIG_SZ] = { + 0xEA, 0xA7, 0x5C, 0xF6, 0x91, 0x7C, 0x77, 0x91, + 0xC5, 0x33, 0x16, 0x6D, 0x74, 0xFF, 0xCE, 0xCD, + 0x27, 0xE3, 0x47, 0xF6, 0x82, 0x1D, 0x4B, 0xB1, + 0x32, 0x70, 0x88, 0xFC, 0x69, 0xFF, 0x6C, 0x02, + }; + memcpy(&pcrMask, policy, sizeof(pcrMask)); + pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask, pcrArray, sizeof(pcrArray)); + wolfBoot_tpm2_extend(pcrArray[0], (uint8_t*)digest, __LINE__); + } + TPM2_ForceZero(secret, sizeof(secretSz)); return ret; } diff --git a/tools/keytools/sign.c b/tools/keytools/sign.c index 95e473ac2..1b853a35c 100644 --- a/tools/keytools/sign.c +++ b/tools/keytools/sign.c @@ -1224,7 +1224,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, } } else { - /* in manual mode PCR signature */ + /* in manual mode remainder is PCR signature */ io_sz = (int)fread(policy, 1, CMD.policy_sz, f); fclose(f); if (io_sz <= 0) { @@ -1233,6 +1233,15 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, } CMD.policy_sz = io_sz; } + + /* save copy of signed policy including 4 byte header to file */ + snprintf((char*)buf, sizeof(buf), "%s.sig", CMD.policy_file); + printf("Saving policy signature to %s\n", (char*)buf); + f = fopen((char*)buf, "w+b"); + if (f != NULL) { + fwrite(policy, 1, CMD.policy_sz + sizeof(uint32_t), f); + fclose(f); + } } #ifdef DEBUG_SIGNTOOL diff --git a/tools/tpm/policy_create.c b/tools/tpm/policy_create.c index c0ff4e39f..971064212 100644 --- a/tools/tpm/policy_create.c +++ b/tools/tpm/policy_create.c @@ -109,20 +109,20 @@ static void printHexString(const unsigned char* bin, unsigned long sz, printf("\n"); } -static void tpm_mask_sel_pcr(uint32_t pcrMask, uint8_t* pcrArray, - uint32_t* pcrArraySz) +uint32_t wolfBoot_tpm_pcrmask_sel(uint32_t pcrMask, uint8_t* pcrArray, + uint32_t pcrArraySz) { int i; - *pcrArraySz = 0; + uint32_t pcrArraySzAct = 0; for (i=0; i= PCR_SELECT_MAX*2) { + pcrArray[pcrArraySzAct++] = i; + if (pcrArraySzAct < pcrArraySz) { /* make sure we have room */ break; } } } + return pcrArraySzAct; } int TPM2_PCR_Policy_Create(TPM_ALG_ID pcrAlg, @@ -263,7 +263,8 @@ int main(int argc, char *argv[]) pcrArray[pcrArraySz++] = DEFAULT_PCR; } else { - tpm_mask_sel_pcr(pcrMask, pcrArray, &pcrArraySz); + pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask, + pcrArray, sizeof(pcrArray)); } }