You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Firmware format is auto-detected from TPM firmware version:
137
149
- Firmware < 512: Non-LMS format (177 byte manifest)
@@ -199,3 +211,81 @@ Success: Please reset or power cycle TPM
199
211
```
200
212
201
213
**Note**: Firmware files cannot be made public and must be obtained separately from STMicroelectronics.
214
+
215
+
## Policy-Based Authorization (Advanced)
216
+
217
+
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.
218
+
219
+
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:
220
+
221
+
-**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. Note this applies to the *library*: the `--policy`/`--policyor` example modes are themselves such a caller, and their helper (`examples/firmware/firmware_policy.c`) does overwrite the platform `authPolicy` with a digest it generates. Do not run those modes on a system whose platform hierarchy already carries a policy you need.
222
+
-**ST33**: the supplied session replaces the default `TPM_RS_PW` password authorization.
223
+
224
+
**Supported session contract**: the vendor `FieldUpgradeStart` command is sent with an authorization area carrying only the session handle - empty `nonceCaller`, zero session attributes and an empty HMAC. The supplied session must therefore be an unsalted, unbound `TPM_SE_POLICY` session with no auth value and no parameter encryption. Policies satisfied with `wolfTPM2_PolicyAuthValue()` or `wolfTPM2_PolicyPassword()` are **not** supported, because the session HMAC they require is not serialized on this path; such a session is rejected with `BAD_FUNC_ARG` before anything is sent to the TPM. `PolicyPCR`, `PolicySigned`, `PolicySecret`, `PolicyAuthorize`, `PolicyCommandCode` and `PolicyOR` branches are all fine.
225
+
226
+
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.
227
+
228
+
Example: satisfy a multi-branch `PolicyOR` (up to 8 branches, SHA2-512 shown) and start the upgrade under it:
229
+
230
+
```c
231
+
WOLFTPM2_SESSION session;
232
+
TPML_DIGEST orList;
233
+
uint8_t manifest_hash[TPM_SHA512_DIGEST_SIZE];
234
+
int rc;
235
+
236
+
/* zero both structs - orList must not carry uninitialized branch sizes */
237
+
XMEMSET(&session, 0, sizeof(session));
238
+
XMEMSET(&orList, 0, sizeof(orList));
239
+
240
+
/* start a policy session using the desired policy hash (SHA2-512 for PQC) */
/* On a successful FieldUpgradeStart the TPM consumes the session and the
265
+
* library sets session.handle.hndl to TPM_RH_NULL (0x40000007) - it is NOT
266
+
* zeroed, so do not test for == 0 to detect consumption. Calling
267
+
* wolfTPM2_UnloadHandle is always safe: it is a no-op on TPM_RH_NULL, so this
268
+
* only releases a session that is still loaded. */
269
+
if (session.handle.hndl != 0)
270
+
wolfTPM2_UnloadHandle(&dev, &session.handle);
271
+
```
272
+
273
+
Passing `NULL` for the final `startSession` argument makes `wolfTPM2_FirmwareUpgradeHash_ex()` behave exactly like `wolfTPM2_FirmwareUpgradeHash()` (library-managed authorization), so existing code is unaffected.
274
+
275
+
### Destructive: provisioning replaces any existing platform policy
276
+
277
+
`--policy`/`--policyor` call `TPM2_SetPrimaryPolicy` on the platform hierarchy with a digest the example generates. TPM 2.0 provides **no way to read a hierarchy's `authPolicy` back** - there is no read command, and `TPMA_PERMANENT` reports only `authValue` state - so the example cannot detect an existing policy, cannot preserve it, and cannot restore it. Cleanup **removes** the policy rather than restoring whatever was there before.
278
+
279
+
If your platform hierarchy is gated by a policy you need to keep, do not run these modes. The example prints this warning at provisioning time. `--policytest` is unaffected: it is non-destructive and never calls `TPM2_SetPrimaryPolicy`.
280
+
281
+
The modes also require the normal operational mode. In recovery and finalize modes the library skips `FieldUpgradeStart` entirely, so a caller-supplied session would never be used; the example refuses rather than installing a policy nothing will exercise. On ST33, if the TPM is already in firmware-upgrade mode the policy flags are likewise rejected, since the start command has already run.
282
+
283
+
### Rollback of the example-provisioned policy
284
+
285
+
The example `--policy`/`--policyor` modes provision the platform hierarchy `authPolicy` via `TPM2_SetPrimaryPolicy` before the upgrade. On failure the example clears it again so a later default-auth run is not locked out; on success the required TPM reset clears it.
286
+
287
+
- Rollback normally uses platform **password** authorization. Per TPM 2.0 Part 1 Sec.19.7 a hierarchy is authorized by *either* its `authValue` *or* its `authPolicy`, so installing an `authPolicy` does not disable the password path. With the default empty `platformAuth` the clear always succeeds.
288
+
- `--policyor` additionally provisions a `PolicyCommandCode(TPM_CC_SetPrimaryPolicy)` branch alongside the firmware-start branch, so the policy can authorize its own removal. If the password path fails (a deployment that set a non-default `platformAuth`), the example retries the clear under that branch.
289
+
- `--policy` provisions a single `PolicyCommandCode(FieldUpgradeStart)` branch and therefore has no policy-based rollback path. It relies entirely on `platformAuth` still being usable.
290
+
- Rollback is attempted only when the example actually installed the policy, so an early failure (a missing firmware file, for example) never clears a policy the deployment provisioned itself.
291
+
- A failed rollback is reported explicitly and becomes the exit status. If a run is interrupted before cleanup, or the clear fails, the platform hierarchy still requires the policy until the TPM is reset/power-cycled.
0 commit comments