From 4c55c1410c285cfb3a0d75f32873d9810ef72023 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 24 Jul 2026 15:26:16 -0700 Subject: [PATCH] Add caller-supplied policy authorization for firmware upgrade --- examples/firmware/README.md | 39 +++++++ examples/firmware/st33_fw_update.c | 132 ++++++++++++++++++++++++ src/tpm2_wrap.c | 158 ++++++++++++++++++++--------- wolftpm/tpm2_wrap.h | 61 +++++++++++ 4 files changed, 343 insertions(+), 47 deletions(-) diff --git a/examples/firmware/README.md b/examples/firmware/README.md index 66d0c60d6..6c1fde087 100644 --- a/examples/firmware/README.md +++ b/examples/firmware/README.md @@ -199,3 +199,42 @@ Success: Please reset or power cycle TPM ``` **Note**: Firmware files cannot be made public and must be obtained separately from STMicroelectronics. + +## Policy-Based Authorization (Advanced) + +By default wolfTPM manages the platform-hierarchy authorization for the firmware-update *start* command internally: on Infineon it installs and satisfies a `PolicyCommandCode(TPM_CC_FieldUpgradeStartVendor)` policy on the platform primary policy, and on ST33 it uses password authorization (`TPM_RS_PW`) with an empty platform password. This assumes the platform hierarchy has default/empty authorization. + +Deployments that gate firmware upgrade behind their own platform policy (for example a signed-policy check, a PCR state, or a multi-branch `PolicyOR`) can supply an already-satisfied authorization session using `wolfTPM2_FirmwareUpgradeHash_ex()`. When a session is supplied: + +- **Infineon**: the library does **not** overwrite your platform primary policy. You provision the platform `authPolicy` yourself (via `TPM2_SetPrimaryPolicy` with `authHandle = TPM_RH_PLATFORM`, using SHA2-256 or SHA2-512) and pass a session that satisfies it. +- **ST33**: the supplied session replaces the default `TPM_RS_PW` password authorization. + +Both SHA2-256 (non-PQC) and SHA2-512 (PQC) policy digests are supported, because the session hash is chosen with `wolfTPM2_StartSession_ex(..., authHash)` and `wolfTPM2_PolicyOR()` carries per-branch digest sizes. + +Example: satisfy a multi-branch `PolicyOR` (up to 8 branches, SHA2-512 shown) and start the upgrade under it: + +```c +WOLFTPM2_SESSION session; +TPML_DIGEST orList; +uint8_t manifest_hash[TPM_SHA512_DIGEST_SIZE]; + +/* start a policy session using the desired policy hash (SHA2-512 for PQC) */ +XMEMSET(&session, 0, sizeof(session)); +wolfTPM2_StartSession_ex(&dev, &session, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL, TPM_ALG_SHA512); + +/* satisfy one branch (PCR, PolicySigned/Authorize, PolicyAuthValue, ...), + * then OR against the full branch list that the platform authPolicy encodes */ +/* ... build orList.digests[0..count-1] with your pre-computed branch digests ... */ +orList.count = 2; +wolfTPM2_PolicyOR(&dev, &session, &orList); + +/* hash the manifest with the matching algorithm, then start the upgrade under + * the caller-satisfied session (NULL would use the library-default auth) */ +wc_Sha512Hash(manifest, manifest_sz, manifest_hash); +wolfTPM2_FirmwareUpgradeHash_ex(&dev, TPM_ALG_SHA512, + manifest_hash, (uint32_t)sizeof(manifest_hash), + manifest, manifest_sz, fwDataCb, fwCbCtx, &session); +``` + +Passing `NULL` for the final `startSession` argument makes `wolfTPM2_FirmwareUpgradeHash_ex()` behave exactly like `wolfTPM2_FirmwareUpgradeHash()` (library-managed authorization), so existing code is unaffected. diff --git a/examples/firmware/st33_fw_update.c b/examples/firmware/st33_fw_update.c index 2120df3db..5c7e62e9c 100644 --- a/examples/firmware/st33_fw_update.c +++ b/examples/firmware/st33_fw_update.c @@ -47,6 +47,7 @@ static void usage(void) printf("ST33 Firmware Update Usage:\n"); printf("\t./st33_fw_update (get info)\n"); printf("\t./st33_fw_update --abandon (cancel)\n"); + printf("\t./st33_fw_update --policytest (safe policy auth self-test)\n"); printf("\t./st33_fw_update \n"); printf("\nFirmware format is auto-detected from the TPM firmware version.\n"); printf("Just provide the correct .fi file for your TPM and it will be handled automatically.\n"); @@ -173,6 +174,116 @@ static void TPM2_ST33_PrintInfo(WOLFTPM2_CAPS* caps) } } +/* Build a PolicyCommandCode branch digest offline. This matches the running + * policy digest of a fresh policy session after wolfTPM2_PolicyCommandCode. */ +static int BuildPolicyCommandCode(TPMI_ALG_HASH hashAlg, + byte* digest, word32* digestSz, TPM_CC cc) +{ + byte val[4]; /* command code in big-endian, matching the TPM wire format */ + val[0] = (byte)((cc >> 24) & 0xFF); + val[1] = (byte)((cc >> 16) & 0xFF); + val[2] = (byte)((cc >> 8) & 0xFF); + val[3] = (byte)(cc & 0xFF); + return wolfTPM2_PolicyHash(hashAlg, digest, digestSz, + TPM_CC_PolicyCommandCode, val, sizeof(val)); +} + +/* Non-destructive self-test for the caller-supplied policy authorization + * added for firmware upgrade. Exercises wolfTPM2_PolicyOR at the requested + * hash algorithm and verifies the TPM's running policy digest matches an + * offline computation. This does NOT invoke FieldUpgradeStart and never + * changes TPM state persistently, so it is safe to run on a live TPM. + * Returns 0 on match. */ +static int firmware_policy_selftest(WOLFTPM2_DEV* dev, TPMI_ALG_HASH hashAlg, + const char* name) +{ + int rc; + WOLFTPM2_SESSION sess; + TPML_DIGEST orList; + word32 hsz = (word32)TPM2_GetHashDigestSize(hashAlg); + byte branchA[TPM_MAX_DIGEST_SIZE]; + byte branchB[TPM_MAX_DIGEST_SIZE]; + byte concat[2 * TPM_MAX_DIGEST_SIZE]; + byte expected[TPM_MAX_DIGEST_SIZE]; + byte got[TPM_MAX_DIGEST_SIZE]; + word32 aSz, bSz, expSz, gotSz; + + XMEMSET(&sess, 0, sizeof(sess)); + XMEMSET(&orList, 0, sizeof(orList)); + + if (hsz == 0 || hsz > TPM_MAX_DIGEST_SIZE) { + return BAD_FUNC_ARG; + } + + /* Offline: two distinct PolicyCommandCode branch digests */ + XMEMSET(branchA, 0, sizeof(branchA)); + aSz = hsz; + rc = BuildPolicyCommandCode(hashAlg, branchA, &aSz, TPM_CC_NV_Read); + if (rc == 0) { + XMEMSET(branchB, 0, sizeof(branchB)); + bSz = hsz; + rc = BuildPolicyCommandCode(hashAlg, branchB, &bSz, TPM_CC_Unseal); + } + /* Offline PolicyOR digest = H(zeros || TPM_CC_PolicyOR || A || B) */ + if (rc == 0) { + XMEMCPY(concat, branchA, aSz); + XMEMCPY(&concat[aSz], branchB, bSz); + XMEMSET(expected, 0, sizeof(expected)); + expSz = hsz; + rc = wolfTPM2_PolicyHash(hashAlg, expected, &expSz, + TPM_CC_PolicyOR, concat, aSz + bSz); + } + + /* On-TPM: start a policy session using the requested hash algorithm */ + if (rc == 0) { + rc = wolfTPM2_StartSession_ex(dev, &sess, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL, hashAlg); + if (rc != 0) { + printf(" %s: StartSession failed 0x%x: %s\n", + name, rc, TPM2_GetRCString(rc)); + return rc; + } + } + /* Satisfy branch A, then OR against {A,B} with the new wrapper */ + if (rc == 0) { + rc = wolfTPM2_PolicyCommandCode(dev, &sess, TPM_CC_NV_Read); + } + if (rc == 0) { + orList.count = 2; + orList.digests[0].size = (UINT16)aSz; + XMEMCPY(orList.digests[0].buffer, branchA, aSz); + orList.digests[1].size = (UINT16)bSz; + XMEMCPY(orList.digests[1].buffer, branchB, bSz); + rc = wolfTPM2_PolicyOR(dev, &sess, &orList); + } + if (rc == 0) { + gotSz = (word32)sizeof(got); + rc = wolfTPM2_GetPolicyDigest(dev, sess.handle.hndl, got, &gotSz); + } + + if (rc == 0) { + if (gotSz == expSz && XMEMCMP(got, expected, expSz) == 0) { + printf(" %s PolicyOR: PASS (%u byte digest matches)\n", + name, expSz); + } + else { + printf(" %s PolicyOR: FAIL (digest mismatch)\n", name); + printf(" expected: "); + TPM2_PrintBin(expected, expSz); + printf(" got: "); + TPM2_PrintBin(got, gotSz); + rc = -1; + } + } + else { + printf(" %s PolicyOR: ERROR 0x%x: %s\n", + name, rc, TPM2_GetRCString(rc)); + } + + wolfTPM2_UnloadHandle(dev, &sess.handle); + return rc; +} + /* Forward declaration */ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[]); @@ -184,6 +295,7 @@ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[]) const char* fi_file = NULL; fw_info_t fwinfo; int abandon = 0; + int policytest = 0; size_t blob0_size; XMEMSET(&fwinfo, 0, sizeof(fwinfo)); @@ -199,6 +311,9 @@ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[]) if (XSTRCMP(argv[1], "--abandon") == 0) { abandon = 1; } + else if (XSTRCMP(argv[1], "--policytest") == 0) { + policytest = 1; + } else { fi_file = argv[1]; } @@ -245,6 +360,23 @@ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[]) goto exit; } + if (policytest) { + /* Non-destructive validation of caller-supplied policy authorization. + * Runs SHA2-256 (non-PQC) and SHA2-512 (PQC) PolicyOR digest checks. + * Does not touch firmware upgrade state. */ + int rc256, rc512; + printf("Firmware policy authorization self-test (no firmware changes):\n"); + rc256 = firmware_policy_selftest(&dev, TPM_ALG_SHA256, "SHA2-256"); + rc512 = firmware_policy_selftest(&dev, TPM_ALG_SHA512, "SHA2-512"); + if (rc512 != 0) { + printf(" Note: a SHA2-512 failure may mean this TPM firmware does" + " not support SHA2-512 policy sessions.\n"); + } + rc = (rc256 == 0) ? rc512 : rc256; + wolfTPM2_Cleanup(&dev); + return rc; + } + rc = wolfTPM2_GetCapabilities(&dev, &caps); if (rc != TPM_RC_SUCCESS) { printf("wolfTPM2_GetCapabilities failed 0x%x: %s\n", diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index d6e179618..785fb1ecb 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -10650,6 +10650,29 @@ int wolfTPM2_PolicyCommandCode(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, return TPM2_PolicyCommandCode(&policyCC); } +/* Satisfy a policy session with a compound OR of pre-computed policy digests. + * The digest list is hash-agnostic (each branch carries its own size), so it + * works for SHA2-256 as well as SHA2-512 policy branches. */ +int wolfTPM2_PolicyOR(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, + const TPML_DIGEST* pHashList) +{ + PolicyOR_In policyOR; + + if (dev == NULL || tpmSession == NULL || pHashList == NULL) { + return BAD_FUNC_ARG; + } + if (pHashList->count == 0 || + pHashList->count > (word32)(sizeof(pHashList->digests) / + sizeof(pHashList->digests[0]))) { + return BAD_FUNC_ARG; + } + + XMEMSET(&policyOR, 0, sizeof(policyOR)); + policyOR.policySession = tpmSession->handle.hndl; + XMEMCPY(&policyOR.pHashList, pHashList, sizeof(policyOR.pHashList)); + return TPM2_PolicyOR(&policyOR); +} + #ifndef WOLFTPM2_NO_WOLFCRYPT /* Authorize a policy based on external key for a verified policy digiest signature */ int wolfTPM2_PolicyAuthorize(WOLFTPM2_DEV* dev, TPM_HANDLE sessionHandle, @@ -11077,52 +11100,70 @@ static int tpm2_ifx_firmware_enable_policy(WOLFTPM2_DEV* dev) } static int tpm2_ifx_firmware_start(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, - uint8_t* manifest_hash, uint32_t manifest_hash_sz) + uint8_t* manifest_hash, uint32_t manifest_hash_sz, + WOLFTPM2_SESSION* startSession) { int rc; WOLFTPM2_SESSION tpmSession; + TPM_HANDLE sessionHandle = TPM_RH_NULL; + int ownSession = 0; XMEMSET(&tpmSession, 0, sizeof(tpmSession)); - rc = wolfTPM2_StartSession(dev, &tpmSession, NULL, NULL, - TPM_SE_POLICY, TPM_ALG_NULL); - if (rc == TPM_RC_SUCCESS) { - rc = wolfTPM2_PolicyCommandCode(dev, &tpmSession, - TPM_CC_FieldUpgradeStartVendor); + if (startSession != NULL) { + /* Caller has already satisfied the platform policy on this session */ + sessionHandle = startSession->handle.hndl; + rc = TPM_RC_SUCCESS; + } + else { + /* Default: internal policy session asserting the firmware start + * command code, matching the policy installed on the platform + * hierarchy by tpm2_ifx_firmware_enable_policy */ + rc = wolfTPM2_StartSession(dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL); if (rc == TPM_RC_SUCCESS) { - /* build command for manifest header */ - uint16_t val16; - /* max cmd: type (1) + data sz (2) + hash alg (2) + max digest (64) */ - uint8_t cmd[1 + 2 + 2 + TPM_SHA512_DIGEST_SIZE]; - cmd[0] = 0x01; /* type */ - val16 = be16_to_cpu(manifest_hash_sz + 2); - XMEMCPY(&cmd[1], &val16, sizeof(val16)); /* data size */ - val16 = be16_to_cpu(hashAlg); - XMEMCPY(&cmd[3], &val16, sizeof(val16)); /* hash algorithm */ - XMEMCPY(&cmd[5], manifest_hash, manifest_hash_sz); - - rc = TPM2_IFX_FieldUpgradeStart(tpmSession.handle.hndl, - cmd, 1 + 2 + 2 + manifest_hash_sz); - } - if (rc == TPM_RC_SUCCESS) { - /* delay to give the TPM time to switch modes */ - XSLEEP_MS(300); - /* it is not required to release session handle, - * since TPM reset into firmware upgrade mode */ - - #if !defined(WOLFTPM_LINUX_DEV) && !defined(WOLFTPM_SWTPM) && \ - !defined(WOLFTPM_WINAPI) - /* Do chip startup and request locality again */ - #ifdef WOLFTPM_LINUX_DEV_AUTODETECT - if (dev->ctx.fd < 0) /* Only needed for SPI path */ - #endif - rc = TPM2_ChipStartup(&dev->ctx, 10); - #endif - } - else { - wolfTPM2_UnloadHandle(dev, &tpmSession.handle); + ownSession = 1; + sessionHandle = tpmSession.handle.hndl; + rc = wolfTPM2_PolicyCommandCode(dev, &tpmSession, + TPM_CC_FieldUpgradeStartVendor); } } + + if (rc == TPM_RC_SUCCESS) { + /* build command for manifest header */ + uint16_t val16; + /* max cmd: type (1) + data sz (2) + hash alg (2) + max digest (64) */ + uint8_t cmd[1 + 2 + 2 + TPM_SHA512_DIGEST_SIZE]; + cmd[0] = 0x01; /* type */ + val16 = be16_to_cpu(manifest_hash_sz + 2); + XMEMCPY(&cmd[1], &val16, sizeof(val16)); /* data size */ + val16 = be16_to_cpu(hashAlg); + XMEMCPY(&cmd[3], &val16, sizeof(val16)); /* hash algorithm */ + XMEMCPY(&cmd[5], manifest_hash, manifest_hash_sz); + + rc = TPM2_IFX_FieldUpgradeStart(sessionHandle, + cmd, 1 + 2 + 2 + manifest_hash_sz); + } + + if (rc == TPM_RC_SUCCESS) { + /* delay to give the TPM time to switch modes */ + XSLEEP_MS(300); + /* it is not required to release session handle, + * since TPM reset into firmware upgrade mode */ + + #if !defined(WOLFTPM_LINUX_DEV) && !defined(WOLFTPM_SWTPM) && \ + !defined(WOLFTPM_WINAPI) + /* Do chip startup and request locality again */ + #ifdef WOLFTPM_LINUX_DEV_AUTODETECT + if (dev->ctx.fd < 0) /* Only needed for SPI path */ + #endif + rc = TPM2_ChipStartup(&dev->ctx, 10); + #endif + } + else if (ownSession) { + /* only release a session we started ourselves */ + wolfTPM2_UnloadHandle(dev, &tpmSession.handle); + } #ifdef DEBUG_WOLFTPM if (rc != TPM_RC_SUCCESS) { printf("Firmware upgrade start failed 0x%x: %s\n", @@ -11278,7 +11319,7 @@ static int tpm2_ifx_firmware_final(WOLFTPM2_DEV* dev) static int tpm2_st33_firmware_upgrade_hash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, uint8_t* manifest_hash, uint32_t manifest_hash_sz, uint8_t* manifest, uint32_t manifest_sz, - wolfTPM2FwDataCb cb, void* cb_ctx); + wolfTPM2FwDataCb cb, void* cb_ctx, WOLFTPM2_SESSION* startSession); static int tpm2_st33_firmware_cancel(WOLFTPM2_DEV* dev); #endif @@ -11286,6 +11327,17 @@ int wolfTPM2_FirmwareUpgradeHash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, uint8_t* manifest_hash, uint32_t manifest_hash_sz, uint8_t* manifest, uint32_t manifest_sz, wolfTPM2FwDataCb cb, void* cb_ctx) +{ + /* Default behavior: library-managed platform authorization */ + return wolfTPM2_FirmwareUpgradeHash_ex(dev, hashAlg, + manifest_hash, manifest_hash_sz, manifest, manifest_sz, + cb, cb_ctx, NULL); +} + +int wolfTPM2_FirmwareUpgradeHash_ex(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, + uint8_t* manifest_hash, uint32_t manifest_hash_sz, + uint8_t* manifest, uint32_t manifest_sz, + wolfTPM2FwDataCb cb, void* cb_ctx, WOLFTPM2_SESSION* startSession) { int rc; WOLFTPM2_CAPS caps; @@ -11303,7 +11355,7 @@ int wolfTPM2_FirmwareUpgradeHash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, return tpm2_st33_firmware_upgrade_hash(dev, hashAlg, manifest_hash, manifest_hash_sz, manifest, manifest_sz, - cb, cb_ctx); + cb, cb_ctx, startSession); } #endif @@ -11319,10 +11371,15 @@ int wolfTPM2_FirmwareUpgradeHash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, return tpm2_ifx_firmware_final(dev); } if (caps.opMode == 0x00) { - rc = tpm2_ifx_firmware_enable_policy(dev); + /* When the caller supplies a session it must already satisfy the + * platform authPolicy, so do not overwrite the platform primary + * policy - only manage it for the library-default path */ + if (startSession == NULL) { + rc = tpm2_ifx_firmware_enable_policy(dev); + } if (rc == TPM_RC_SUCCESS) { rc = tpm2_ifx_firmware_start(dev, hashAlg, - manifest_hash, manifest_hash_sz); + manifest_hash, manifest_hash_sz, startSession); } } if (rc == TPM_RC_SUCCESS) { @@ -11461,17 +11518,23 @@ int wolfTPM2_FirmwareUpgradeCancel(WOLFTPM2_DEV* dev) * 300ms delay: ST reference implementation uses this delay to allow * TPM to switch modes after FieldUpgradeStart command */ static int tpm2_st33_firmware_start_common(WOLFTPM2_DEV* dev, - uint8_t* manifest, uint32_t manifest_sz, int is_lms) + uint8_t* manifest, uint32_t manifest_sz, int is_lms, + WOLFTPM2_SESSION* startSession) { int rc; + TPM_HANDLE sessionHandle; (void)dev; - /* ST33 uses password auth (TPM_RS_PW) for FieldUpgradeStart. - * This matches the ST reference implementation behavior. + /* By default ST33 uses password auth (TPM_RS_PW) for FieldUpgradeStart, + * matching the ST reference implementation behavior. When the caller + * supplies a session (for example a policy session that satisfies a + * custom platform authPolicy), use it instead. * For LMS format, the manifest (blob0) already contains the embedded * LMS signature. Send the full manifest directly. */ - rc = TPM2_ST33_FieldUpgradeStart(TPM_RS_PW, manifest, manifest_sz); + sessionHandle = (startSession != NULL) ? + startSession->handle.hndl : (TPM_HANDLE)TPM_RS_PW; + rc = TPM2_ST33_FieldUpgradeStart(sessionHandle, manifest, manifest_sz); if (rc == TPM_RC_SUCCESS) { /* 300ms delay: ST reference implementation uses this delay to allow @@ -11630,7 +11693,7 @@ static int tpm2_st33_firmware_data(WOLFTPM2_DEV* dev, static int tpm2_st33_firmware_upgrade_hash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg, uint8_t* manifest_hash, uint32_t manifest_hash_sz, uint8_t* manifest, uint32_t manifest_sz, - wolfTPM2FwDataCb cb, void* cb_ctx) + wolfTPM2FwDataCb cb, void* cb_ctx, WOLFTPM2_SESSION* startSession) { int rc; WOLFTPM2_CAPS caps; @@ -11704,7 +11767,8 @@ static int tpm2_st33_firmware_upgrade_hash(WOLFTPM2_DEV* dev, TPM_ALG_ID hashAlg } /* Send manifest - the common function handles both LMS and non-LMS */ - rc = tpm2_st33_firmware_start_common(dev, manifest, manifest_sz, is_lms); + rc = tpm2_st33_firmware_start_common(dev, manifest, manifest_sz, is_lms, + startSession); if (rc == TPM_RC_SUCCESS) { rc = tpm2_st33_firmware_data(dev, cb, cb_ctx); diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 108b30934..eee333b0e 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -4976,6 +4976,28 @@ WOLFTPM_API int wolfTPM2_PolicyAuthValue(WOLFTPM2_DEV* dev, WOLFTPM_API int wolfTPM2_PolicyCommandCode(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, TPM_CC cc); +/*! + \ingroup wolfTPM2_Wrappers + + \brief Wrapper for satisfying a policy session with a compound OR of digests + + \note The digest list is hash-agnostic (each branch carries its own size), + so it supports SHA2-256 and SHA2-512 policy branches. Up to 8 branches. + + \return TPM_RC_SUCCESS: successful + \return BAD_FUNC_ARG: check the provided arguments (count 0 or > 8) + + \param dev pointer to a TPM2_DEV struct + \param tpmSession pointer to a WOLFTPM2_SESSION struct used with wolfTPM2_StartSession and wolfTPM2_SetAuthSession + \param pHashList list of pre-computed policy branch digests to OR together + + \sa wolfTPM2_PolicyPCR + \sa wolfTPM2_PolicyAuthorize + \sa wolfTPM2_GetPolicyDigest +*/ +WOLFTPM_API int wolfTPM2_PolicyOR(WOLFTPM2_DEV* dev, + WOLFTPM2_SESSION* tpmSession, const TPML_DIGEST* pHashList); + /* Pre-provisioned IAK and IDevID key/cert from TPM vendor */ /* Tested with ST33KTPM devices */ @@ -5108,6 +5130,45 @@ WOLFTPM_API int wolfTPM2_FirmwareUpgradeHash(WOLFTPM2_DEV* dev, uint8_t* manifest, uint32_t manifest_sz, wolfTPM2FwDataCb cb, void* cb_ctx); +/*! + \ingroup wolfTPM2_Wrappers + \brief Perform TPM firmware upgrade using a caller-supplied authorization session + \note Identical to wolfTPM2_FirmwareUpgradeHash except the caller controls how + the firmware-start command is authorized against the platform hierarchy. + \note When startSession is NULL this behaves exactly like + wolfTPM2_FirmwareUpgradeHash (library-managed platform authorization). + \note When startSession is non-NULL the caller is responsible for having + satisfied the platform authPolicy on that session (for example via + wolfTPM2_PolicyPCR / wolfTPM2_PolicyAuthorize / wolfTPM2_PolicyOR using + SHA2-256 or SHA2-512). For Infineon the platform primary policy is left + untouched (the caller provisions it); for ST33 the session replaces the + default TPM_RS_PW password authorization. + + \return TPM_RC_SUCCESS: successful + \return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code) + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a TPM2_DEV struct + \param hashAlg hash algorithm to use (TPM_ALG_SHA384 or TPM_ALG_SHA512) + \param manifest_hash buffer to store computed manifest hash + \param manifest_hash_sz size of manifest hash buffer + \param manifest pointer to firmware manifest data + \param manifest_sz size of firmware manifest + \param cb callback function for firmware data access + \param cb_ctx context pointer passed to callback + \param startSession optional caller-satisfied session authorizing the + firmware-start command (NULL for library-managed authorization) + + \sa wolfTPM2_FirmwareUpgradeHash + \sa wolfTPM2_PolicyOR + \sa wolfTPM2_StartSession_ex +*/ +WOLFTPM_API int wolfTPM2_FirmwareUpgradeHash_ex(WOLFTPM2_DEV* dev, + TPM_ALG_ID hashAlg, /* Can use SHA2-384 or SHA2-512 for manifest hash */ + uint8_t* manifest_hash, uint32_t manifest_hash_sz, + uint8_t* manifest, uint32_t manifest_sz, + wolfTPM2FwDataCb cb, void* cb_ctx, WOLFTPM2_SESSION* startSession); + #ifndef WOLFTPM2_NO_WOLFCRYPT /*! \ingroup wolfTPM2_Wrappers