diff --git a/.github/workflows/test-build-sim-tpm.yml b/.github/workflows/test-build-sim-tpm.yml index 887ccd07..74771c94 100644 --- a/.github/workflows/test-build-sim-tpm.yml +++ b/.github/workflows/test-build-sim-tpm.yml @@ -16,7 +16,10 @@ on: rot-args: required: false type: string - authstr: + keyauthstr: + required: false + type: string + sealauthstr: required: false type: string @@ -59,7 +62,7 @@ jobs: - name: Write TPM ROT to TPM run: | - ./tools/tpm/rot -write ${{inputs.rot-args}} -auth="${{inputs.authstr}}" + ./tools/tpm/rot -write ${{inputs.rot-args}} -auth="${{inputs.keyauthstr}}" - name: Create a PCR Policy run: | @@ -69,7 +72,7 @@ jobs: - name: Build wolfboot run: | - make ${{inputs.make-args}} WOLFBOOT_TPM_KEYSTORE_AUTH="${{inputs.authstr}}" + make ${{inputs.make-args}} WOLFBOOT_TPM_KEYSTORE_AUTH="${{inputs.keykeyauthstr}}" WOLFBOOT_TPM_SEAL_AUTH="${{inputs.sealauthstr}}" - name: Run wolfBoot run: | diff --git a/.github/workflows/test-tpm.yml b/.github/workflows/test-tpm.yml index ee864c82..0b190364 100644 --- a/.github/workflows/test-tpm.yml +++ b/.github/workflows/test-tpm.yml @@ -65,7 +65,7 @@ jobs: arch: host config-file: ./config/examples/sim-tpm-keystore.config make-args: SIGN=ECC256 HASH=SHA256 - authstr: TestAuth + keyauthstr: TestAuth sim_tpm_keystore_ecc384: uses: ./.github/workflows/test-build-sim-tpm.yml @@ -74,7 +74,7 @@ jobs: config-file: ./config/examples/sim-tpm-keystore.config make-args: SIGN=ECC384 HASH=SHA384 rot-args: -sha384 - authstr: TestAuth + keyauthstr: TestAuth sim_tpm_keystore_rsa2048: uses: ./.github/workflows/test-build-sim-tpm.yml @@ -82,7 +82,7 @@ jobs: arch: host config-file: ./config/examples/sim-tpm-keystore.config make-args: SIGN=RSA2048 HASH=SHA256 - authstr: TestAuth + keyauthstr: TestAuth sim_tpm_keystore_noauth_ecc256: @@ -114,7 +114,8 @@ jobs: arch: host config-file: ./config/examples/sim-tpm-seal.config make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin - authstr: TestAuth + keyauthstr: TestAuth + sealauthstr: SealAuth sim_tpm_seal_ecc384: uses: ./.github/workflows/test-build-sim-tpm.yml @@ -123,7 +124,8 @@ jobs: config-file: ./config/examples/sim-tpm-seal.config make-args: SIGN=ECC384 HASH=SHA384 POLICY_FILE=policy.bin rot-args: -sha384 - authstr: TestAuth + keyauthstr: TestAuth + sealauthstr: SealAuth sim_tpm_seal_rsa2048: uses: ./.github/workflows/test-build-sim-tpm.yml @@ -132,4 +134,32 @@ jobs: config-file: ./config/examples/sim-tpm-seal.config # use larger image header size for two 2048-bit signatures make-args: SIGN=RSA2048ENC HASH=SHA256 POLICY_FILE=policy.bin IMAGE_HEADER_SIZE=1024 - authstr: TestAuth + keyauthstr: TestAuth + sealauthstr: SealAuth + + + sim_tpm_seal_noauth_ecc256: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-seal.config + make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin + keyauthstr: TestAuth + + sim_tpm_seal_noauth_ecc384: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-seal.config + make-args: SIGN=ECC384 HASH=SHA384 POLICY_FILE=policy.bin + rot-args: -sha384 + keyauthstr: TestAuth + + sim_tpm_seal_noauth_rsa2048: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-seal.config + # use larger image header size for two 2048-bit signatures + make-args: SIGN=RSA2048ENC HASH=SHA256 POLICY_FILE=policy.bin IMAGE_HEADER_SIZE=1024 + keyauthstr: TestAuth diff --git a/config/examples/sim-tpm-seal.config b/config/examples/sim-tpm-seal.config index c22f12cb..ff1b9496 100644 --- a/config/examples/sim-tpm-seal.config +++ b/config/examples/sim-tpm-seal.config @@ -29,6 +29,7 @@ MEASURED_PCR_A?=16 # Sealing a secret into TPM based on external PCR policy signed by the sign tool WOLFBOOT_TPM_SEAL?=1 WOLFBOOT_TPM_SEAL_NV_BASE=0x01400300 +#WOLFBOOT_TPM_SEAL_AUTH?=SealAuth # TPM Logging #CFLAGS_EXTRA+=-DDEBUG_WOLFTPM diff --git a/docs/TPM.md b/docs/TPM.md index 0976a2dd..e8439c65 100644 --- a/docs/TPM.md +++ b/docs/TPM.md @@ -15,6 +15,7 @@ In wolfBoot we support TPM based root of trust, sealing/unsealing, cryptographic | `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. | | `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 | ## Root of Trust (ROT) @@ -36,14 +37,14 @@ The wolfBoot image is hashed and extended to the indicated PCR. This can be used See the wolfTPM Sealing/Unsealing example [here](https://github.com/wolfSSL/wolfTPM/tree/secret_seal/examples/boot#secure-boot-encryption-key-storage) Known PCR values must be signed to seal/unseal a secret. The signature for the authorization policy resides in the signed header using the `--policy` argument. -If a signed policy is not in the header then a value cannot be sealed. Instead the PCR(s) and a digest to sign will be printed for use with the sign tool. +If a signed policy is not in the header then a value cannot be sealed. Instead the PCR(s) values and a PCR policy digest will be printed to sign. You can use `./tools/keytools/sign` or `./tools/tpm/policy_sign` to sign the policy externally. This exposes two new wolfBoot API's for sealing and unsealing data with blob stored to NV index: ```c -int wolfBoot_seal(uint8_t* pubkey_hint, uint8_t* policy, uint16_t policySz, - int index, const uint8_t* secret, int secret_sz); -int wolfBoot_unseal(uint8_t* pubkey_hint, uint8_t* policy, uint16_t policySz, - int index, uint8_t* secret, int* secret_sz); +int wolfBoot_seal_auth(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, + int index, const uint8_t* secret, int secret_sz, const byte* auth, int authSz); +int wolfBoot_unseal_auth(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, + int index, uint8_t* secret, int* secret_sz, const byte* auth, int authSz); ``` By default this index will be based on an NV Index at `(0x01400300 + index)`. @@ -62,7 +63,8 @@ NOTE: The TPM's RSA verify requires ASN.1 encoding, so use SIGN=RSA2048ENC % ./tools/tpm/policy_create -pcr=0 # if ROT enabled % ./tools/tpm/rot -write [-auth=TestAuth] -% make clean && make POLICY_FILE=policy.bin +% make clean +$ make POLICY_FILE=policy.bin [WOLFBOOT_TPM_KEYSTORE_AUTH=TestAuth] [WOLFBOOT_TPM_SEAL_AUTH=SealAuth] % ./wolfboot.elf get_version Simulator assigned ./internal_flash.dd to base 0x103378000 diff --git a/include/tpm.h b/include/tpm.h index 6ec0e3fc..a1fc89bc 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -72,10 +72,14 @@ int wolfBoot_get_policy(struct wolfBoot_image* img, int wolfBoot_seal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, int index, const uint8_t* secret, int secret_sz); +int wolfBoot_seal_auth(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, + int index, const uint8_t* secret, int secret_sz, const uint8_t* auth, int authSz); int wolfBoot_seal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, WOLFTPM2_KEYBLOB* seal_blob, const uint8_t* secret, int secret_sz); int wolfBoot_unseal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, int index, uint8_t* secret, int* secret_sz); +int wolfBoot_unseal_auth(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, + int index, uint8_t* secret, int* secret_sz, const uint8_t* auth, int authSz); int wolfBoot_unseal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, WOLFTPM2_KEYBLOB* seal_blob, uint8_t* secret, int* secret_sz); @@ -102,7 +106,7 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line); /* debugging */ void wolfBoot_print_hexstr(const unsigned char* bin, unsigned long sz, unsigned long maxLine); -void wolfBoot_print_bin(const byte* buffer, word32 length); +void wolfBoot_print_bin(const uint8_t* buffer, uint32_t length); #else diff --git a/options.mk b/options.mk index d66bb371..b9cd5709 100644 --- a/options.mk +++ b/options.mk @@ -28,6 +28,9 @@ endif ifeq ($(WOLFBOOT_TPM_SEAL),1) WOLFTPM:=1 CFLAGS+=-D"WOLFBOOT_TPM_SEAL" + ifneq ($(WOLFBOOT_TPM_SEAL_AUTH),) + CFLAGS+=-DWOLFBOOT_TPM_SEAL_AUTH='"$(WOLFBOOT_TPM_SEAL_AUTH)"' + endif ifneq ($(WOLFBOOT_TPM_SEAL_NV_BASE),) CFLAGS+=-D"WOLFBOOT_TPM_SEAL_NV_BASE=$(WOLFBOOT_TPM_SEAL_NV_BASE)" endif diff --git a/src/tpm.c b/src/tpm.c index 24390d9f..a165c0c9 100644 --- a/src/tpm.c +++ b/src/tpm.c @@ -605,9 +605,9 @@ int wolfBoot_store_blob(TPMI_RH_NV_AUTH authHandle, uint32_t nvIndex, nvSz = (uint32_t)sizeof(blob->pub.size) + blob->pub.size; nvSz += (uint32_t)sizeof(blob->priv.size) + blob->priv.size; - /* Create NV - no auth required, blob encrypted by TPM already */ + /* Create NV */ rc = wolfTPM2_NVCreateAuth(&wolftpm_dev, &parent, &nv, - nv.handle.hndl, nvAttributes, nvSz, NULL, 0); + nv.handle.hndl, nvAttributes, nvSz, auth, authSz); if (rc == TPM_RC_NV_DEFINED) { /* allow use of existing handle - ignore this error */ rc = 0; @@ -739,7 +739,8 @@ int wolfBoot_delete_blob(TPMI_RH_NV_AUTH authHandle, uint32_t nvIndex, } /* The secret is sealed based on a policy authorization from a public key. */ -int wolfBoot_seal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, +int wolfBoot_seal_blob(const uint8_t* pubkey_hint, + const uint8_t* policy, uint16_t policySz, WOLFTPM2_KEYBLOB* seal_blob, const uint8_t* secret, int secret_sz) { int rc; @@ -801,8 +802,9 @@ int wolfBoot_seal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16 /* Create a new key for sealing using external signing auth */ wolfTPM2_GetKeyTemplate_KeySeal(&template, pcrAlg); rc = wolfTPM2_CreateKeySeal_ex(&wolftpm_dev, seal_blob, - &wolftpm_srk.handle, &template, NULL, 0, pcrAlg, NULL, 0, - secret, secret_sz); + &wolftpm_srk.handle, &template, + seal_blob->handle.auth.buffer, seal_blob->handle.auth.size, + pcrAlg, NULL, 0, secret, secret_sz); } wolfTPM2_UnloadHandle(&wolftpm_dev, &policy_session.handle); @@ -813,8 +815,10 @@ int wolfBoot_seal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16 /* Index (0-X) determines location in NV from WOLFBOOT_TPM_SEAL_NV_BASE to * store sealed blob */ -int wolfBoot_seal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, - int index, const uint8_t* secret, int secret_sz) +int wolfBoot_seal_auth(const uint8_t* pubkey_hint, + const uint8_t* policy, uint16_t policySz, + int index, const uint8_t* secret, int secret_sz, + const uint8_t* auth, int authSz) { int rc; WOLFTPM2_KEYBLOB seal_blob; @@ -822,6 +826,9 @@ int wolfBoot_seal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t po memset(&seal_blob, 0, sizeof(seal_blob)); + seal_blob.handle.auth.size = authSz; + XMEMCPY(seal_blob.handle.auth.buffer, auth, authSz); + /* creates a sealed keyed hash object (not loaded to TPM) */ rc = wolfBoot_seal_blob(pubkey_hint, policy, policySz, &seal_blob, secret, secret_sz); @@ -841,8 +848,7 @@ int wolfBoot_seal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t po rc = wolfBoot_store_blob(TPM_RH_PLATFORM, WOLFBOOT_TPM_SEAL_NV_BASE + index, - nvAttributes, &seal_blob, - NULL, 0 /* auth is not required as blob is already encrypted */ + nvAttributes, &seal_blob, auth, authSz ); } if (rc != 0) { @@ -851,6 +857,19 @@ int wolfBoot_seal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t po } return rc; } +int wolfBoot_seal(const uint8_t* pubkey_hint, + const uint8_t* policy, uint16_t policySz, + int index, const uint8_t* secret, int secret_sz) +{ + const char* auth = NULL; + int authSz = 0; +#ifdef WOLFBOOT_TPM_SEAL_AUTH + auth = WOLFBOOT_TPM_SEAL_AUTH; + authSz = (int)strlen(auth); +#endif + return wolfBoot_seal_auth(pubkey_hint, policy, policySz, index, + secret, secret_sz, (const uint8_t*)auth, authSz); +} /* The unseal requires a signed policy from HDR_POLICY_SIGNATURE */ int wolfBoot_unseal_blob(const uint8_t* pubkey_hint, @@ -999,8 +1018,10 @@ int wolfBoot_unseal_blob(const uint8_t* pubkey_hint, return rc; } -int wolfBoot_unseal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t policySz, - int index, uint8_t* secret, int* secret_sz) +int wolfBoot_unseal_auth(const uint8_t* pubkey_hint, + const uint8_t* policy, uint16_t policySz, + int index, uint8_t* secret, int* secret_sz, + const uint8_t* auth, int authSz) { int rc; WOLFTPM2_KEYBLOB seal_blob; @@ -1008,8 +1029,7 @@ int wolfBoot_unseal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t memset(&seal_blob, 0, sizeof(seal_blob)); rc = wolfBoot_read_blob(WOLFBOOT_TPM_SEAL_NV_BASE + index, &seal_blob, - NULL, 0 /* auth is not required as sealed blob is already encrypted */ - ); + auth, authSz); if (rc == 0) { rc = wolfBoot_unseal_blob(pubkey_hint, policy, policySz, &seal_blob, secret, secret_sz); @@ -1026,6 +1046,19 @@ int wolfBoot_unseal(const uint8_t* pubkey_hint, const uint8_t* policy, uint16_t } return rc; } +int wolfBoot_unseal(const uint8_t* pubkey_hint, + const uint8_t* policy, uint16_t policySz, + int index, uint8_t* secret, int* secret_sz) +{ + const char* auth = NULL; + int authSz = 0; +#ifdef WOLFBOOT_TPM_SEAL_AUTH + auth = WOLFBOOT_TPM_SEAL_AUTH; + authSz = (int)strlen(auth); +#endif + return wolfBoot_unseal_auth(pubkey_hint, policy, policySz, index, + secret, secret_sz, (const uint8_t*)auth, authSz); +} #endif /* WOLFBOOT_TPM_SEAL */ #if (defined(WOLFBOOT_TPM_KEYSTORE) || defined(WOLFBOOT_TPM_SEAL)) && \