From cbf3cffa96af65fc66f7909d07e4ad5867f20438 Mon Sep 17 00:00:00 2001 From: John Bland Date: Thu, 4 May 2023 20:49:02 -0400 Subject: [PATCH 1/4] add script for preseal a public key to tpm add more detailed instructions on how to prepare a TPM keystore build and how to use the preseal script --- Makefile | 3 + docs/PubkeySealing.md | 22 +++-- tools/preseal/Makefile | 12 +++ tools/preseal/preseal | Bin 0 -> 16856 bytes tools/preseal/preseal.c | 195 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 tools/preseal/Makefile create mode 100755 tools/preseal/preseal create mode 100644 tools/preseal/preseal.c diff --git a/Makefile b/Makefile index f6e0846f..af88dbaa 100644 --- a/Makefile +++ b/Makefile @@ -153,6 +153,9 @@ keytools: @$(MAKE) -C tools/keytools clean @$(MAKE) -C tools/keytools +preseal: + @$(MAKE) -C tools/preseal + test-app/image_v1_signed.bin: $(BOOT_IMG) @echo "\t[SIGN] $(BOOT_IMG)" $(Q)(test $(SIGN) = NONE) || $(SIGN_TOOL) $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1 diff --git a/docs/PubkeySealing.md b/docs/PubkeySealing.md index d4fc20d6..17bfd386 100644 --- a/docs/PubkeySealing.md +++ b/docs/PubkeySealing.md @@ -8,24 +8,36 @@ Next you need to use external signing to sign the image you want to include and ``` echo -n -e '\x00\x00\x00\x00' > zeroExpiry -openssl dgst -sha256 -sign policy_signed_ecc.pem -out policySigned zeroExpiry +openssl dgst -sha256 -sign policy-key.pem -out policySigned zeroExpiry #extract the raw key signature, should be 64 bytes openssl asn1parse -inform DER -in policySigned echo "4BDAC51C517C0F3D8EDBB632B514262C256E289565A2F1CD8605A4F775302C0CD7BBFE0242CAA536A30C87A37756C390DB9A2B06037B15476A509CA06B857B6D" | xxd -r -p - policySigned.raw +#extract the raw policy-key public section +openssl ec -in policy-key.pem -text -noout +echo "925a8a35dbe4bd419a35fbf9bd30ce1440380f6d3bcd9bc5558c1fa8adb88d92c88b797dfca39af80ca9729c61508813df8254575cef48674071cf75c30e6aa8" | xxd -r -p - policy-public-key.raw +openssl ec -in private-key.pem -text -noout +echo "925a8a35dbe4bd419a35fbf9bd30ce1440380f6d3bcd9bc5558c1fa8adb88d92c88b797dfca39af80ca9729c61508813df8254575cef48674071cf75c30e6aa8" | xxd -r -p - public-key.raw ``` -Next we need to manually make the image signature +Next we need to manually make the image signature, note that the header contains the policy pubkey instead of the real pubkey which will be sealed to the tpm: ``` -tools/keytools/sign --ecc256 --sha256 --sha-only test-app/image.elf policy-public-key.raw 1 -openssl pkeyutl -sign -inkey private-key.pem -in test-app/image_v1_digest.bin > test-app/image_v1.sig +tools/keytools/sign --ecc256 --sha256 --sha-only image.elf policy-public-key.raw 1 +openssl pkeyutl -sign -inkey private-key.pem -in test-app/image_v1_digest.bin > imageSignature +openssl asn1parse -inform DER -in imageSignature echo "6C7B61198E1575F21FB6FFE3D65AE267BF72CC7A660105F61D9130CE1351320685A41D401F3B453951C06A3150DBC51F9B7CFA39748079B489E6C1CFAECF2EBF" | xxd -r -p - imageSignature.raw ``` Next you need to create the image using the sign keytool with the --manual-sign option and the --policy-sign option: ``` -tools/keytools/sign --ecc256 --sha256 --manual-sign --policy-signed my_image.bin policy_signed_ecc.raw 1 imageSignature.raw policySigned.raw +tools/keytools/sign --ecc256 --sha256 --manual-sign --policy-signed my_image policy-public-key.raw 1 imageSignature.raw policySigned.raw +``` + +Lastly, the pubkey needs to be sealed to the TPM: + +``` +tools/preseal/preseal public-key.raw policy-public-key.raw policySigned.raw test-app/image_v1_digest.bin 0x01800200 0x01800201 16 ``` ## NOTE: the PolicySigned key is used in place of the real signing key and acts as an intermediate key to unseal the actual signing key form the TPM diff --git a/tools/preseal/Makefile b/tools/preseal/Makefile new file mode 100644 index 00000000..d7de8fcc --- /dev/null +++ b/tools/preseal/Makefile @@ -0,0 +1,12 @@ +CC = gcc + +all: preseal + +preseal: + $(Q)$(CC) -o $@ $@.c -lwolftpm + +debug: + $(Q)$(CC) -o preseal preseal.c -g -lwolftpm -lwolfssl + +clean: + rm -f preseal diff --git a/tools/preseal/preseal b/tools/preseal/preseal new file mode 100755 index 0000000000000000000000000000000000000000..089cb45ae4c821c3296bff011efe7f7d8e105eb0 GIT binary patch literal 16856 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 j_c^%kPWz|VD6ZQj +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEFAULT_PCR_INDEX 16 + +static int readFile(char* name, uint8_t* buf, uint32_t* bufSz) +{ + int ret; + int fd; + struct stat st; + + /* check size */ + ret = stat(name, &st); + + if (ret == 0) { + if (st.st_size > *bufSz) + return INPUT_SIZE_E; + + fd = open(name, O_RDONLY); + + if (fd < 0) + ret = fd; + } + + /* read the contents */ + if (ret == 0) { + ret = read(fd, buf, st.st_size); + + if (ret >= 0) { + *bufSz = ret; + ret = 0; + } + + close(fd); + } + + return ret; +} + +static void usage() +{ + printf("preseal pubkey policypubkey policysignature imagedigest sealNVindex digestNVindex [pcrindex]\n"); + printf("pubkey: the verification key to seal into the tpm\n"); + printf("policypubkey: the pubkey used sign the policy expiration date\n"); + printf("policysignature: the signature of the policy expiration date\n"); + printf("imagedigest: the digest of the image that this pubkey verifies\n"); + printf("sealNVindex: the NV index to seal the pubkey to\n"); + printf("digestNVindex: the NV index to seal the policyDigest to\n"); + printf("pcrindex: the pcrindex to extend with the imagedigest, defaults to 16\n"); +} + +int main(int argc, char** argv) +{ + int rc = -1; + WOLFTPM2_DEV dev; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_KEY authKey; + PCR_Reset_In pcrReset; + /* default to aes since parm encryption is required */ + TPM_ALG_ID paramEncAlg = TPM_ALG_CFB; + uint8_t pcrArray[48]; + uint32_t pcrArraySz = 1; + uint8_t pubkey[ECC_MAXSIZE]; + uint32_t pubkeySz = ECC_MAXSIZE; + uint8_t policyPubkey[ECC_MAXSIZE]; + uint32_t policyPubkeySz = ECC_MAXSIZE; + uint8_t policySigned[ECC_MAXSIZE]; + uint32_t policySignedSz = ECC_MAXSIZE; + uint8_t imageDigest[WC_MAX_DIGEST_SIZE]; + uint32_t imageDigestSz = WC_MAX_DIGEST_SIZE; + uint32_t sealNvIndex; + uint32_t policyDigestNvIndex; + +#ifdef DEBUG_SIGNTOOL + wolfSSL_Debugging_ON(); +#endif + + if (argc < 7) { + usage(); + return 0; + } + + XMEMSET(&dev, 0, sizeof(WOLFTPM2_DEV)); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + XMEMSET(&authKey, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(&pcrReset, 0, sizeof(PCR_Reset_In)); + + rc = readFile(argv[1], pubkey, &pubkeySz); + if (rc != 0) { + printf("Failed to read pubkey\n"); + return 1; + } + + rc = readFile(argv[2], policyPubkey, &policyPubkeySz); + if (rc != 0) { + printf("Failed to read policypubkey\n"); + return 1; + } + + rc = readFile(argv[3], policySigned, &policySignedSz); + if (rc != 0) { + printf("Failed to read policysignature\n"); + return 1; + } + + rc = readFile(argv[4], imageDigest, &imageDigestSz); + if (rc != 0) { + printf("Failed to read imagedigest\n"); + return 1; + } + + sealNvIndex = atoi(argv[5]); + policyDigestNvIndex = atoi(argv[6]); + + /* TODO change this to a loop when multiple pcr's are supported */ + if (argc > 7 ) + pcrArray[0] = atoi(argv[7]); + else + pcrArray[0] = DEFAULT_PCR_INDEX; + + rc = wolfTPM2_Init(&dev, NULL, NULL); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + pcrReset.pcrHandle = pcrArray[0]; + + rc = TPM2_PCR_Reset(&pcrReset); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_PCR_Reset failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + rc = wolfTPM2_ExtendPCR(&dev, pcrArray[0], TPM_ALG_SHA256, + imageDigest, imageDigestSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_ExtendPCR failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_StartSession failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SetAuthSession failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + rc = wolfTPM2_LoadEccPublicKey(&dev, (WOLFTPM2_KEY*)&authKey, + TPM_ECC_NIST_P256, policyPubkey, 32, policyPubkey + 32, 32); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadEccPublicKey failed\n"); + goto exit; + } + + rc = wolfTPM2_SealWithAuthSigNV(&dev, &authKey, &tpmSession, TPM_ALG_SHA256, + TPM_ALG_SHA256, (word32*)pcrArray, pcrArraySz, pubkey, pubkeySz, NULL, + 0, policySigned, policySignedSz, sealNvIndex, policyDigestNvIndex); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SealWithAuthPolicyNV failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + +exit: + if (rc != 0) { + printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_UnloadHandle(&dev, &authKey.handle); + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + wolfTPM2_Cleanup(&dev); + + return rc; +} From fa071065f6bd9917871d60f0f2c64daf0907cfae Mon Sep 17 00:00:00 2001 From: John Bland Date: Thu, 4 May 2023 22:58:20 -0400 Subject: [PATCH 2/4] update preseal based on pr comments --- .gitignore | 4 ++++ tools/preseal/preseal | Bin 16856 -> 0 bytes tools/preseal/preseal.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+) delete mode 100755 tools/preseal/preseal diff --git a/.gitignore b/.gitignore index 7758f82f..c6d1e24f 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,10 @@ tools/keytools/x64 tools/keytools/Debug tools/keytools/Release +# preseal binary +tools/preseal/preseal +tools/preseal/preseal.exe + # delta binaries tools/delta/bmdiff tools/delta/bmpatch diff --git a/tools/preseal/preseal b/tools/preseal/preseal deleted file mode 100755 index 089cb45ae4c821c3296bff011efe7f7d8e105eb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16856 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 j_c^%kPWz|VD6ZQj #include #include From a654eb057e7a814bda7ce4f46df2c63e59e9f85a Mon Sep 17 00:00:00 2001 From: John Bland Date: Thu, 4 May 2023 23:12:49 -0400 Subject: [PATCH 3/4] fix hex formating and clarify where to run preseal command --- docs/PubkeySealing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/PubkeySealing.md b/docs/PubkeySealing.md index 17bfd386..d0abf31a 100644 --- a/docs/PubkeySealing.md +++ b/docs/PubkeySealing.md @@ -34,10 +34,10 @@ Next you need to create the image using the sign keytool with the --manual-sign tools/keytools/sign --ecc256 --sha256 --manual-sign --policy-signed my_image policy-public-key.raw 1 imageSignature.raw policySigned.raw ``` -Lastly, the pubkey needs to be sealed to the TPM: +Lastly, the pubkey needs to be sealed to the TPM. Note that the previous commands could be run from a seperate system, this one must be run on a system connected to the TPM: ``` -tools/preseal/preseal public-key.raw policy-public-key.raw policySigned.raw test-app/image_v1_digest.bin 0x01800200 0x01800201 16 +tools/preseal/preseal public-key.raw policy-public-key.raw policySigned.raw test-app/image_v1_digest.bin 25166336 25166337 16 ``` ## NOTE: the PolicySigned key is used in place of the real signing key and acts as an intermediate key to unseal the actual signing key form the TPM From bf3ebee8bb60c6e612b6bd4b59384765a62255f5 Mon Sep 17 00:00:00 2001 From: John Bland Date: Fri, 5 May 2023 16:27:22 -0400 Subject: [PATCH 4/4] use correct digest when getting unsealing the pubkey add deinit call when wolfboot exits so the TPM doesn't have a hanging session --- docs/PubkeySealing.md | 2 +- include/image.h | 3 +- include/loader.h | 1 + src/image.c | 89 +++++++++++++++++++++++++++++++++---------- src/libwolfboot.c | 4 +- src/update_flash.c | 3 ++ 6 files changed, 77 insertions(+), 25 deletions(-) diff --git a/docs/PubkeySealing.md b/docs/PubkeySealing.md index d0abf31a..6f46a798 100644 --- a/docs/PubkeySealing.md +++ b/docs/PubkeySealing.md @@ -19,7 +19,7 @@ openssl ec -in private-key.pem -text -noout echo "925a8a35dbe4bd419a35fbf9bd30ce1440380f6d3bcd9bc5558c1fa8adb88d92c88b797dfca39af80ca9729c61508813df8254575cef48674071cf75c30e6aa8" | xxd -r -p - public-key.raw ``` -Next we need to manually make the image signature, note that the header contains the policy pubkey instead of the real pubkey which will be sealed to the tpm: +Next we need to manually make the image signature, note that the header contains the policy pubkey instead of the real pubkey which will be sealed to the TPM: ``` tools/keytools/sign --ecc256 --sha256 --sha-only image.elf policy-public-key.raw 1 diff --git a/include/image.h b/include/image.h index 5cd25433..a9973536 100644 --- a/include/image.h +++ b/include/image.h @@ -558,8 +558,7 @@ uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr); #if defined(WOLFBOOT_TPM) && defined(WOLFTPM_KEYSTORE) #if defined(WOLFTPM_ENCRYPT_KEYSTORE) && defined(EXT_ENCRYPTED) -int wolfBoot_unseal_encryptkey(struct wolfBoot_image *img, uint8_t* key, - uint32_t* keySz); +int wolfBoot_unseal_encryptkey(uint8_t* key, uint32_t* keySz); #endif int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, diff --git a/include/loader.h b/include/loader.h index 1f7f996d..e7e2c7d6 100644 --- a/include/loader.h +++ b/include/loader.h @@ -67,6 +67,7 @@ extern "C" { #ifdef WOLFBOOT_TPM int wolfBoot_tpm2_init(void); + void wolfBoot_tpm2_deinit(void); #endif void wolfBoot_start(void); diff --git a/src/image.c b/src/image.c index 35b79f39..44cce54b 100644 --- a/src/image.c +++ b/src/image.c @@ -43,8 +43,7 @@ static WOLFTPM2_DEV wolftpm_dev; static uint8_t wolftpmPcrArray[1] = {WOLFTPM_PCR_INDEX}; -static int wolfBoot_unseal_pubkey(struct wolfBoot_image *img, uint8_t* pubkey, - WOLFTPM2_KEY* tpmKey); +static int wolfBoot_unseal_pubkey(uint8_t* pubkey, WOLFTPM2_KEY* tpmKey); #endif #endif /* WOLFBOOT_TPM */ @@ -142,7 +141,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, if (ret < 0) return; #ifdef WOLFTPM_KEYSTORE - ret = wolfBoot_unseal_pubkey(img, pubkey, &tpmKey); + ret = wolfBoot_unseal_pubkey(pubkey, &tpmKey); if (ret < 0) return; #endif @@ -780,9 +779,6 @@ int wolfBoot_tpm2_init(void) #ifndef ARCH_SIM spi_init(0,0); #endif -#ifdef WOLFTPM_KEYSTORE - PCR_Reset_In pcrReset; -#endif /* Init the TPM2 device */ /* simulator should use the network connection, not spi */ @@ -804,15 +800,20 @@ int wolfBoot_tpm2_init(void) return 0; } +void wolfBoot_tpm2_deinit(void) +{ + wolfTPM2_Cleanup(&wolftpm_dev); +} + /* Currently only supports ecc256 */ #ifdef WOLFTPM_KEYSTORE #if defined(WOLFTPM_ENCRYPT_KEYSTORE) && defined(EXT_ENCRYPTED) -int wolfBoot_unseal_encryptkey(struct wolfBoot_image *img, uint8_t* key, - uint32_t* keySz) +int wolfBoot_unseal_encryptkey(uint8_t* key, uint32_t* keySz) { WOLFTPM2_SESSION wolftpm_session; WOLFTPM2_KEY tpmKey; PCR_Reset_In pcrReset; + struct wolfBoot_image boot; uint8_t* pubkey; uint8_t* pubkeyHint; uint8_t* policySignature; @@ -820,12 +821,23 @@ int wolfBoot_unseal_encryptkey(struct wolfBoot_image *img, uint8_t* key, int ret; uint16_t pubkeyHintSize; uint16_t policySignatureSz; + uint8_t bootDigest[WOLFBOOT_SHA_DIGEST_SIZE]; + XMEMSET(&wolftpm_session, 0, sizeof(WOLFTPM2_SESSION)); XMEMSET(&tpmKey, 0, sizeof(tpmKey)); XMEMSET(&pcrReset, 0, sizeof(PCR_Reset_In)); + /* get the boot partition, PCR is always set to boot hash */ + ret = wolfBoot_open_image(&boot, PART_BOOT); + if (ret != 0) + return ret; + + /* get the boot digest */ + if (image_hash(&boot, bootDigest) != 0) + return -1; + /* find the keyslot of the public key */ - pubkeyHintSize = get_header(img, HDR_PUBKEY, &pubkeyHint); + pubkeyHintSize = get_header(&boot, HDR_PUBKEY, &pubkeyHint); if (pubkeyHintSize != WOLFBOOT_SHA_DIGEST_SIZE) return -1; /* Invalid hash size for public key hint */ @@ -847,7 +859,7 @@ int wolfBoot_unseal_encryptkey(struct wolfBoot_image *img, uint8_t* key, /* extend the PCRs with the image hash */ ret = wolfTPM2_ExtendPCR(&wolftpm_dev, wolftpmPcrArray[0], TPM_ALG_SHA256, - img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); + bootDigest, WOLFBOOT_SHA_DIGEST_SIZE); if (ret != TPM_RC_SUCCESS) return -ret; @@ -876,7 +888,7 @@ int wolfBoot_unseal_encryptkey(struct wolfBoot_image *img, uint8_t* key, return -ret; /* get the PolicySigned signature tlv */ - policySignatureSz = get_header(img, HDR_POLICY_SIGNATURE, &policySignature); + policySignatureSz = get_header(&boot, HDR_POLICY_SIGNATURE, &policySignature); if (policySignatureSz != IMAGE_SIGNATURE_SIZE) return -1; @@ -917,7 +929,9 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, uint16_t policySignatureSz; uint16_t pubkeyHintSize; uint8_t tpmPubkey[KEYSTORE_PUBKEY_SIZE_ECC256]; + uint8_t workingDigest[WOLFBOOT_SHA_DIGEST_SIZE]; + XMEMSET(&wolftpm_session, 0, sizeof(WOLFTPM2_SESSION)); XMEMSET(&tpmKey, 0, sizeof(tpmKey)); XMEMSET(&pcrReset, 0, sizeof(PCR_Reset_In)); @@ -935,6 +949,10 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, if (pubkey == NULL) return -1; + /* get the backupImg hash */ + if (image_hash(backupImg, workingDigest) != 0) + return -1; + /* clear out the PCR digest */ pcrReset.pcrHandle = wolftpmPcrArray[0]; @@ -944,7 +962,7 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, /* extend the PCRs with the backupImg hash */ ret = wolfTPM2_ExtendPCR(&wolftpm_dev, wolftpmPcrArray[0], TPM_ALG_SHA256, - backupImg->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); + workingDigest, WOLFBOOT_SHA_DIGEST_SIZE); if (ret != TPM_RC_SUCCESS) return -ret; @@ -1001,11 +1019,21 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, return -ret; #endif - /* unload the session handle */ - wolfTPM2_SetAuthSession(&wolftpm_dev, 0, NULL, 0); - + /* unload the key and session handle */ + wolfTPM2_UnloadHandle(&wolftpm_dev, &tpmKey.handle); wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_session.handle); + wolfBoot_tpm2_deinit(); + wolfBoot_tpm2_init(); + + XMEMSET(&wolftpm_session, 0, sizeof(WOLFTPM2_SESSION)); + XMEMSET(&tpmKey, 0, sizeof(tpmKey)); + XMEMSET(&pcrReset, 0, sizeof(PCR_Reset_In)); + + /* get the newImg hash */ + if (image_hash(newImg, workingDigest) != 0) + return -1; + /* clear out the PCR digest */ pcrReset.pcrHandle = wolftpmPcrArray[0]; @@ -1015,7 +1043,7 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, /* extend the PCRs with the newImg hash */ ret = wolfTPM2_ExtendPCR(&wolftpm_dev, wolftpmPcrArray[0], TPM_ALG_SHA256, - newImg->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); + workingDigest, WOLFBOOT_SHA_DIGEST_SIZE); if (ret != TPM_RC_SUCCESS) return -ret; @@ -1036,6 +1064,13 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, if (ret != TPM_RC_SUCCESS) return -ret; + /* Load public key into TPM */ + ret = wolfTPM2_LoadEccPublicKey(&wolftpm_dev, &tpmKey, TPM_ECC_NIST_P256, + pubkey, KEYSTORE_ECC_POINT_SIZE, pubkey + KEYSTORE_ECC_POINT_SIZE, + KEYSTORE_ECC_POINT_SIZE); + if (ret < 0) + return -ret; + /* seal the NV key with the new policyDigest*/ ret = wolfTPM2_SealWithAuthSigNV(&wolftpm_dev, &tpmKey, &wolftpm_session, TPM_ALG_SHA256, TPM_ALG_SHA256, (word32*)wolftpmPcrArray, @@ -1066,25 +1101,39 @@ int wolfBoot_reseal_keys(struct wolfBoot_image* newImg, wolfTPM2_UnloadHandle(&wolftpm_dev, &wolftpm_session.handle); + wolfBoot_tpm2_deinit(); + wolfBoot_tpm2_init(); + return 0; } -static int wolfBoot_unseal_pubkey(struct wolfBoot_image *img, uint8_t* pubkey, - WOLFTPM2_KEY* tpmKey) +static int wolfBoot_unseal_pubkey(uint8_t* pubkey, WOLFTPM2_KEY* tpmKey) { WOLFTPM2_SESSION wolftpm_session; PCR_Reset_In pcrReset; PCR_SetAuthPolicy_In setAuthPolicy; + struct wolfBoot_image boot; int ret; uint8_t* policySignature; uint32_t pubkeySz = KEYSTORE_PUBKEY_SIZE_ECC256; uint32_t tpmPubkeySz = KEYSTORE_PUBKEY_SIZE_ECC256; uint16_t policySignatureSz; uint8_t tpmPubkey[KEYSTORE_PUBKEY_SIZE_ECC256]; + uint8_t bootDigest[WOLFBOOT_SHA_DIGEST_SIZE]; + XMEMSET(&wolftpm_session, 0, sizeof(WOLFTPM2_SESSION)); XMEMSET(&pcrReset, 0, sizeof(PCR_Reset_In)); XMEMSET(&setAuthPolicy, 0, sizeof(PCR_Reset_In)); + /* get the boot partition, PCR is always set to boot hash */ + ret = wolfBoot_open_image(&boot, PART_BOOT); + if (ret != 0) + return ret; + + /* get the boot digest */ + if (image_hash(&boot, bootDigest) != 0) + return -1; + /* clear out the PCR digest */ pcrReset.pcrHandle = wolftpmPcrArray[0]; @@ -1094,7 +1143,7 @@ static int wolfBoot_unseal_pubkey(struct wolfBoot_image *img, uint8_t* pubkey, /* extend the PCRs with the image hash */ ret = wolfTPM2_ExtendPCR(&wolftpm_dev, wolftpmPcrArray[0], TPM_ALG_SHA256, - img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); + bootDigest, WOLFBOOT_SHA_DIGEST_SIZE); if (ret != TPM_RC_SUCCESS) return -ret; @@ -1116,7 +1165,7 @@ static int wolfBoot_unseal_pubkey(struct wolfBoot_image *img, uint8_t* pubkey, return -ret; /* get the PolicySigned signature tlv */ - policySignatureSz = get_header(img, HDR_POLICY_SIGNATURE, &policySignature); + policySignatureSz = get_header(&boot, HDR_POLICY_SIGNATURE, &policySignature); if (policySignatureSz != IMAGE_SIGNATURE_SIZE) return -1; diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 1ae766e8..921c79d4 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -1040,7 +1040,7 @@ int RAMFUNCTION chacha_init(void) #ifdef WOLFTPM_ENCRYPT_KEYSTORE wolfBoot_open_image(&boot, PART_BOOT); - if (wolfBoot_unseal_encryptkey(&boot, key, &keySz) != 0) + if (wolfBoot_unseal_encryptkey(key, &keySz) != 0) return -1; #endif @@ -1086,7 +1086,7 @@ int aes_init(void) #ifdef WOLFTPM_ENCRYPT_KEYSTORE wolfBoot_open_image(&boot, PART_BOOT); - if (wolfBoot_unseal_encryptkey(&boot, key, &keySz) != 0) + if (wolfBoot_unseal_encryptkey(key, &keySz) != 0) return -1; #endif diff --git a/src/update_flash.c b/src/update_flash.c index ad3b599b..ec1b6632 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -557,6 +557,9 @@ void RAMFUNCTION wolfBoot_start(void) } } PART_SANITY_CHECK(&boot); +#ifdef WOLFBOOT_TPM + wolfBoot_tpm2_deinit(); +#endif hal_prepare_boot(); do_boot((void *)boot.fw_base); }