@@ -2580,17 +2580,26 @@ static TPM_RC FwCmd_ContextSave(FWTPM_CTX* ctx, TPM2_Packet* cmd,
25802580 TPM2_Packet_AppendU32 (rsp , hierarchy );
25812581
25822582 if (isSession && sess != NULL ) {
2583- /* Session: serialize full FWTPM_Session into blob and free slot.
2584- * Format: magic(4) | version(4) | FWTPM_Session (raw struct) */
2585- blobSz = 4 + 4 + (UINT16 )sizeof (FWTPM_Session );
2586- TPM2_Packet_AppendU16 (rsp , blobSz );
2587- tmp32 = TPM2_Packet_SwapU32 (FWTPM_CTX_MAGIC );
2588- TPM2_Packet_AppendBytes (rsp , (byte * )& tmp32 , 4 );
2589- tmp32 = TPM2_Packet_SwapU32 (FWTPM_CTX_VER );
2590- TPM2_Packet_AppendBytes (rsp , (byte * )& tmp32 , 4 );
2591- TPM2_Packet_AppendBytes (rsp , (byte * )sess , sizeof (FWTPM_Session ));
2592- /* Free the session slot — ContextLoad will restore it */
2593- XMEMSET (sess , 0 , sizeof (FWTPM_Session ));
2583+ /* Session: HMAC + AES-CFB protected blob per TPM 2.0 §30.
2584+ * Format: magic(4) | version(4) | wrappedBlob(iv+cipher+hmac) */
2585+ byte wrappedBuf [AES_BLOCK_SIZE + sizeof (FWTPM_Session ) +
2586+ WC_SHA256_DIGEST_SIZE ];
2587+ int wrappedSz = 0 ;
2588+ rc = FwWrapContextBlob (ctx , (const byte * )sess ,
2589+ (int )sizeof (FWTPM_Session ),
2590+ wrappedBuf , (int )sizeof (wrappedBuf ), & wrappedSz );
2591+ if (rc == 0 ) {
2592+ blobSz = 4 + 4 + (UINT16 )wrappedSz ;
2593+ TPM2_Packet_AppendU16 (rsp , blobSz );
2594+ tmp32 = TPM2_Packet_SwapU32 (FWTPM_CTX_MAGIC );
2595+ TPM2_Packet_AppendBytes (rsp , (byte * )& tmp32 , 4 );
2596+ tmp32 = TPM2_Packet_SwapU32 (FWTPM_CTX_VER );
2597+ TPM2_Packet_AppendBytes (rsp , (byte * )& tmp32 , 4 );
2598+ TPM2_Packet_AppendBytes (rsp , wrappedBuf , wrappedSz );
2599+ }
2600+ TPM2_ForceZero (wrappedBuf , sizeof (wrappedBuf ));
2601+ /* Free the session slot */
2602+ TPM2_ForceZero (sess , sizeof (FWTPM_Session ));
25942603 }
25952604 else {
25962605 /* Object: opaque handle reference (object stays in slot).
@@ -2660,14 +2669,44 @@ static TPM_RC FwCmd_ContextLoad(FWTPM_CTX* ctx, TPM2_Packet* cmd,
26602669
26612670 if ((savedHandle & 0xFF000000 ) == HMAC_SESSION_FIRST ||
26622671 (savedHandle & 0xFF000000 ) == POLICY_SESSION_FIRST ) {
2663- /* Session context: restore FWTPM_Session from blob into free slot */
2664- if (dataLen != (UINT16 )sizeof (FWTPM_Session )) {
2672+ /* Session context: verify integrity + decrypt, then restore.
2673+ * Wrapped blob: iv(16) + ciphertext(sizeof(FWTPM_Session)) + hmac(32) */
2674+ int expectedWrapSz = AES_BLOCK_SIZE +
2675+ (int )sizeof (FWTPM_Session ) + WC_SHA256_DIGEST_SIZE ;
2676+ FWTPM_Session restored ;
2677+ int restoredSz = 0 ;
2678+ int si ;
2679+ int found = 0 ;
2680+
2681+ if ((int )dataLen != expectedWrapSz ) {
26652682 rc = TPM_RC_SIZE ;
26662683 }
26672684 if (rc == 0 ) {
2668- /* Restore session to any free slot */
2669- int si ;
2670- int found = 0 ;
2685+ byte wrappedBuf [AES_BLOCK_SIZE + sizeof (FWTPM_Session ) +
2686+ WC_SHA256_DIGEST_SIZE ];
2687+ TPM2_Packet_ParseBytes (cmd , wrappedBuf , (int )dataLen );
2688+ rc = FwUnwrapContextBlob (ctx , wrappedBuf , (int )dataLen ,
2689+ (byte * )& restored , (int )sizeof (restored ), & restoredSz );
2690+ TPM2_ForceZero (wrappedBuf , sizeof (wrappedBuf ));
2691+ if (rc != 0 ) {
2692+ /* HMAC mismatch or decrypt failure */
2693+ if (rc != TPM_RC_INTEGRITY )
2694+ rc = TPM_RC_INTEGRITY ;
2695+ }
2696+ }
2697+ /* Validate deserialized session fields */
2698+ if (rc == 0 ) {
2699+ if (restored .sessionType != TPM_SE_HMAC &&
2700+ restored .sessionType != TPM_SE_POLICY &&
2701+ restored .sessionType != TPM_SE_TRIAL ) {
2702+ rc = TPM_RC_VALUE ;
2703+ }
2704+ if (TPM2_GetHashDigestSize (restored .authHash ) <= 0 ) {
2705+ rc = TPM_RC_VALUE ;
2706+ }
2707+ }
2708+ if (rc == 0 ) {
2709+ /* Find a free session slot */
26712710 for (si = 0 ; si < FWTPM_MAX_SESSIONS ; si ++ ) {
26722711 if (!ctx -> sessions [si ].used ) {
26732712 found = 1 ;
@@ -2677,14 +2716,15 @@ static TPM_RC FwCmd_ContextLoad(FWTPM_CTX* ctx, TPM2_Packet* cmd,
26772716 if (!found ) {
26782717 rc = TPM_RC_SESSION_MEMORY ;
26792718 }
2680- if (rc == 0 ) {
2681- TPM2_Packet_ParseBytes (cmd , (byte * )& ctx -> sessions [si ],
2682- sizeof (FWTPM_Session ));
2683- /* Keep the original handle — cpHash includes session
2684- * handle as entity name, so it must match what ESYS
2685- * computed. FwFindSession searches by handle value. */
2686- }
26872719 }
2720+ if (rc == 0 ) {
2721+ XMEMCPY (& ctx -> sessions [si ], & restored ,
2722+ sizeof (FWTPM_Session ));
2723+ /* Keep the original handle — cpHash includes session
2724+ * handle as entity name, so it must match what ESYS
2725+ * computed. FwFindSession searches by handle value. */
2726+ }
2727+ TPM2_ForceZero (& restored , sizeof (restored ));
26882728 }
26892729 else if ((savedHandle & 0xFF000000 ) == TRANSIENT_FIRST ) {
26902730 /* Object context: verify object still in slot (opaque handle) */
@@ -7294,6 +7334,15 @@ static TPM_RC FwCmd_PolicyRestart(FWTPM_CTX* ctx, TPM2_Packet* cmd,
72947334 /* Reset policy digest to all zeros */
72957335 XMEMSET (sess -> policyDigest .buffer , 0 , sess -> policyDigest .size );
72967336
7337+ /* Reset all policy-related session flags so stale assertions from
7338+ * prior policy evaluations don't affect future HMAC computation
7339+ * or authorization checks. */
7340+ sess -> isPasswordPolicy = 0 ;
7341+ sess -> isAuthValuePolicy = 0 ;
7342+ sess -> isPPRequired = 0 ;
7343+ sess -> cpHashA .size = 0 ;
7344+ sess -> nameHash .size = 0 ;
7345+
72977346 FwRspFinalize (rsp , TPM_ST_NO_SESSIONS , TPM_RC_SUCCESS );
72987347 }
72997348
@@ -12477,6 +12526,19 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1247712526 authPolicy = & objEnt -> pub .authPolicy ;
1247812527 }
1247912528 }
12529+ /* Hierarchy handles: check SetPrimaryPolicy-assigned policy */
12530+ else if (entityH == TPM_RH_OWNER ) {
12531+ authPolicy = & ctx -> ownerPolicy ;
12532+ }
12533+ else if (entityH == TPM_RH_ENDORSEMENT ) {
12534+ authPolicy = & ctx -> endorsementPolicy ;
12535+ }
12536+ else if (entityH == TPM_RH_PLATFORM ) {
12537+ authPolicy = & ctx -> platformPolicy ;
12538+ }
12539+ else if (entityH == TPM_RH_LOCKOUT ) {
12540+ authPolicy = & ctx -> lockoutPolicy ;
12541+ }
1248012542
1248112543 /* If entity has a non-empty authPolicy, it must match */
1248212544 if (authPolicy != NULL && authPolicy -> size > 0 ) {
0 commit comments