@@ -8228,6 +8228,10 @@ static TPM_RC FwCmd_PolicyAuthorize(FWTPM_CTX* ctx, TPM2_Packet* cmd,
82288228 int expectedSz = 0 ;
82298229 wc_HashAlg aCtx ;
82308230 enum wc_HashType aWcHash ;
8231+ int hmacRc ;
8232+ int sizeMismatch ;
8233+ int ticketDiff ;
8234+ word32 cmpSz ;
82318235
82328236 /* Step 1: aHash = H(approvedPolicy || policyRef)
82338237 * Hash algorithm comes from signing key's nameAlg */
@@ -8254,20 +8258,24 @@ static TPM_RC FwCmd_PolicyAuthorize(FWTPM_CTX* ctx, TPM2_Packet* cmd,
82548258 ticketInputSz += keySignNameSz ;
82558259 }
82568260
8257- /* Step 3: verify ticket HMAC */
8258- if (rc == 0 &&
8259- (FwComputeTicketHmac (ctx , ticketHier , keyNameAlg ,
8260- ticketInput , ticketInputSz ,
8261- expectedHmac , & expectedSz ) != 0 ||
8262- ticketDigestSz != (UINT16 )expectedSz ||
8263- TPM2_ConstantCompare (ticketDigest , expectedHmac ,
8264- (word32 )expectedSz ) != 0 )) {
8265- #ifdef DEBUG_WOLFTPM
8266- printf ("fwTPM: PolicyAuthorize ticket verify failed "
8267- "(tag=0x%x, hier=0x%x, ticketSz=%d, expectedSz=%d)\n" ,
8268- ticketTag , ticketHier , ticketDigestSz , expectedSz );
8269- #endif
8270- rc = TPM_RC_POLICY_FAIL ;
8261+ /* Step 3: verify ticket HMAC — always run TPM2_ConstantCompare
8262+ * so timing doesn't leak size match */
8263+ if (rc == 0 ) {
8264+ hmacRc = FwComputeTicketHmac (ctx , ticketHier , keyNameAlg ,
8265+ ticketInput , ticketInputSz , expectedHmac , & expectedSz );
8266+ sizeMismatch = (ticketDigestSz != (UINT16 )expectedSz );
8267+ cmpSz = (ticketDigestSz < (UINT16 )expectedSz ) ?
8268+ ticketDigestSz : (word32 )expectedSz ;
8269+ ticketDiff = TPM2_ConstantCompare (ticketDigest , expectedHmac ,
8270+ cmpSz );
8271+ if (hmacRc != 0 || (sizeMismatch | ticketDiff )) {
8272+ #ifdef DEBUG_WOLFTPM
8273+ printf ("fwTPM: PolicyAuthorize ticket verify failed "
8274+ "(tag=0x%x, hier=0x%x, ticketSz=%d, expectedSz=%d)\n" ,
8275+ ticketTag , ticketHier , ticketDigestSz , expectedSz );
8276+ #endif
8277+ rc = TPM_RC_POLICY_FAIL ;
8278+ }
82718279 }
82728280 TPM2_ForceZero (aHash , sizeof (aHash ));
82738281 TPM2_ForceZero (expectedHmac , sizeof (expectedHmac ));
@@ -9005,6 +9013,9 @@ static TPM_RC FwCmd_PolicyCpHash(FWTPM_CTX* ctx, TPM2_Packet* cmd,
90059013 FWTPM_Session * sess ;
90069014 UINT16 cpHashSz = 0 ;
90079015 byte cpHashBuf [TPM_MAX_DIGEST_SIZE ];
9016+ int sizeMismatch ;
9017+ int cpDiff ;
9018+ word32 cmpSz ;
90089019 (void )cmdSize ;
90099020
90109021 sess = FwPolicyParseSession (ctx , cmd , cmdSize , cmdTag );
@@ -9025,11 +9036,15 @@ static TPM_RC FwCmd_PolicyCpHash(FWTPM_CTX* ctx, TPM2_Packet* cmd,
90259036 if (rc == 0 ) {
90269037 TPM2_Packet_ParseBytes (cmd , cpHashBuf , cpHashSz );
90279038
9028- /* If cpHashA already set, must be identical */
9039+ /* If cpHashA already set, must be identical — always run
9040+ * TPM2_ConstantCompare so timing doesn't leak size match */
90299041 if (sess -> cpHashA .size > 0 ) {
9030- if (sess -> cpHashA .size != cpHashSz ||
9031- TPM2_ConstantCompare (sess -> cpHashA .buffer , cpHashBuf ,
9032- cpHashSz ) != 0 ) {
9042+ sizeMismatch = (sess -> cpHashA .size != cpHashSz );
9043+ cmpSz = (sess -> cpHashA .size < cpHashSz ) ?
9044+ sess -> cpHashA .size : cpHashSz ;
9045+ cpDiff = TPM2_ConstantCompare (sess -> cpHashA .buffer , cpHashBuf ,
9046+ cmpSz );
9047+ if (sizeMismatch | cpDiff ) {
90339048 rc = TPM_RC_CPHASH ;
90349049 }
90359050 }
@@ -9064,6 +9079,9 @@ static TPM_RC FwCmd_PolicyNameHash(FWTPM_CTX* ctx, TPM2_Packet* cmd,
90649079 FWTPM_Session * sess ;
90659080 UINT16 nameHashSz = 0 ;
90669081 byte nameHashBuf [TPM_MAX_DIGEST_SIZE ];
9082+ int sizeMismatch ;
9083+ int nameDiff ;
9084+ word32 cmpSz ;
90679085 (void )cmdSize ;
90689086
90699087 sess = FwPolicyParseSession (ctx , cmd , cmdSize , cmdTag );
@@ -9084,11 +9102,15 @@ static TPM_RC FwCmd_PolicyNameHash(FWTPM_CTX* ctx, TPM2_Packet* cmd,
90849102 if (rc == 0 ) {
90859103 TPM2_Packet_ParseBytes (cmd , nameHashBuf , nameHashSz );
90869104
9087- /* If nameHash already set, must be identical */
9105+ /* If nameHash already set, must be identical — always run
9106+ * TPM2_ConstantCompare so timing doesn't leak size match */
90889107 if (sess -> nameHash .size > 0 ) {
9089- if (sess -> nameHash .size != nameHashSz ||
9090- TPM2_ConstantCompare (sess -> nameHash .buffer , nameHashBuf ,
9091- nameHashSz ) != 0 ) {
9108+ sizeMismatch = (sess -> nameHash .size != nameHashSz );
9109+ cmpSz = (sess -> nameHash .size < nameHashSz ) ?
9110+ sess -> nameHash .size : nameHashSz ;
9111+ nameDiff = TPM2_ConstantCompare (sess -> nameHash .buffer , nameHashBuf ,
9112+ cmpSz );
9113+ if (sizeMismatch | nameDiff ) {
90929114 rc = TPM_RC_CPHASH ;
90939115 }
90949116 }
@@ -9436,6 +9458,9 @@ static TPM_RC FwCmd_PolicyTicket(FWTPM_CTX* ctx, TPM2_Packet* cmd,
94369458 FWTPM_Session * sess ;
94379459 INT32 expiration = 0 ;
94389460 UINT32 extendCC ;
9461+ int cpaSizeMismatch ;
9462+ int cpaDiff ;
9463+ word32 cpaCmpSz ;
94399464 (void )cmdSize ;
94409465
94419466 TPM2_Packet_ParseU32 (cmd , & sessHandle );
@@ -9522,6 +9547,10 @@ static TPM_RC FwCmd_PolicyTicket(FWTPM_CTX* ctx, TPM2_Packet* cmd,
95229547 enum wc_HashType aWcHash ;
95239548 int aHashSz ;
95249549 byte expBuf [4 ];
9550+ int hmacRc ;
9551+ int sizeMismatch ;
9552+ int ticketDiff ;
9553+ word32 cmpSz ;
95259554
95269555 aWcHash = FwGetWcHashType (sess -> authHash );
95279556 aHashSz = TPM2_GetHashDigestSize (sess -> authHash );
@@ -9551,15 +9580,19 @@ static TPM_RC FwCmd_PolicyTicket(FWTPM_CTX* ctx, TPM2_Packet* cmd,
95519580 ticketInputSz += authNameSz ;
95529581 }
95539582
9554- /* Verify HMAC */
9555- if (rc == 0 &&
9556- (FwComputeTicketHmac (ctx , ticketHier , sess -> authHash ,
9557- ticketInput , ticketInputSz ,
9558- expectedHmac , & expectedSz ) != 0 ||
9559- ticketDigestSz != (UINT16 )expectedSz ||
9560- TPM2_ConstantCompare (ticketDigest , expectedHmac ,
9561- (word32 )expectedSz ) != 0 )) {
9562- rc = TPM_RC_POLICY_FAIL ;
9583+ /* Verify HMAC — always run TPM2_ConstantCompare so timing doesn't
9584+ * leak whether size matched */
9585+ if (rc == 0 ) {
9586+ hmacRc = FwComputeTicketHmac (ctx , ticketHier , sess -> authHash ,
9587+ ticketInput , ticketInputSz , expectedHmac , & expectedSz );
9588+ sizeMismatch = (ticketDigestSz != (UINT16 )expectedSz );
9589+ cmpSz = (ticketDigestSz < (UINT16 )expectedSz ) ?
9590+ ticketDigestSz : (word32 )expectedSz ;
9591+ ticketDiff = TPM2_ConstantCompare (ticketDigest , expectedHmac ,
9592+ cmpSz );
9593+ if (hmacRc != 0 || (sizeMismatch | ticketDiff )) {
9594+ rc = TPM_RC_POLICY_FAIL ;
9595+ }
95639596 }
95649597 TPM2_ForceZero (aHash , sizeof (aHash ));
95659598 TPM2_ForceZero (expectedHmac , sizeof (expectedHmac ));
@@ -9582,13 +9615,18 @@ static TPM_RC FwCmd_PolicyTicket(FWTPM_CTX* ctx, TPM2_Packet* cmd,
95829615 }
95839616 }
95849617
9585- /* Store cpHashA constraint if provided */
9618+ /* Store cpHashA constraint if provided — always run TPM2_ConstantCompare
9619+ * so timing doesn't leak size match */
95869620 if (rc == 0 && cpHashASz > 0 ) {
9587- if (sess -> cpHashA .size > 0 &&
9588- (sess -> cpHashA .size != cpHashASz ||
9589- TPM2_ConstantCompare (sess -> cpHashA .buffer , cpHashABuf ,
9590- cpHashASz ) != 0 )) {
9591- rc = TPM_RC_CPHASH ;
9621+ if (sess -> cpHashA .size > 0 ) {
9622+ cpaSizeMismatch = (sess -> cpHashA .size != cpHashASz );
9623+ cpaCmpSz = (sess -> cpHashA .size < cpHashASz ) ?
9624+ sess -> cpHashA .size : cpHashASz ;
9625+ cpaDiff = TPM2_ConstantCompare (sess -> cpHashA .buffer , cpHashABuf ,
9626+ cpaCmpSz );
9627+ if (cpaSizeMismatch | cpaDiff ) {
9628+ rc = TPM_RC_CPHASH ;
9629+ }
95929630 }
95939631 if (rc == 0 ) {
95949632 sess -> cpHashA .size = cpHashASz ;
@@ -9622,6 +9660,10 @@ static TPM_RC FwCmd_PolicyAuthorizeNV(FWTPM_CTX* ctx, TPM2_Packet* cmd,
96229660 byte ccBuf [4 ];
96239661 UINT32 cc = TPM_CC_PolicyAuthorizeNV ;
96249662 int hashInit = 0 ;
9663+ int nvSizeMismatch ;
9664+ int sessSizeMismatch ;
9665+ int policyDiff ;
9666+ word32 policyCmpSz ;
96259667
96269668 (void )cmdSize ;
96279669
@@ -9657,12 +9699,19 @@ static TPM_RC FwCmd_PolicyAuthorizeNV(FWTPM_CTX* ctx, TPM2_Packet* cmd,
96579699 rc = TPM_RC_HASH ;
96589700 }
96599701
9660- /* For policy sessions (not trial): verify policyDigest == NV data */
9702+ /* For policy sessions (not trial): verify policyDigest == NV data.
9703+ * Always run TPM2_ConstantCompare over min(sizes) so timing doesn't
9704+ * leak size match. */
96619705 if (rc == 0 && sess -> sessionType == TPM_SE_POLICY ) {
9662- if ((int )nv -> nvPublic .dataSize != dSz ||
9663- (int )sess -> policyDigest .size != dSz ||
9664- TPM2_ConstantCompare (sess -> policyDigest .buffer ,
9665- nv -> data , (word32 )dSz ) != 0 ) {
9706+ nvSizeMismatch = ((int )nv -> nvPublic .dataSize != dSz );
9707+ sessSizeMismatch = ((int )sess -> policyDigest .size != dSz );
9708+ policyCmpSz = (sess -> policyDigest .size < nv -> nvPublic .dataSize ) ?
9709+ sess -> policyDigest .size : nv -> nvPublic .dataSize ;
9710+ if (policyCmpSz > (word32 )dSz )
9711+ policyCmpSz = (word32 )dSz ;
9712+ policyDiff = TPM2_ConstantCompare (sess -> policyDigest .buffer ,
9713+ nv -> data , policyCmpSz );
9714+ if (nvSizeMismatch | sessSizeMismatch | policyDiff ) {
96669715 rc = TPM_RC_POLICY_FAIL ;
96679716 }
96689717 }
@@ -12902,6 +12951,9 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1290212951 FWTPM_Session * pSess = cmdAuths [pj ].sess ;
1290312952 TPM_HANDLE entityH = cmdHandles [pj ];
1290412953 TPM2B_DIGEST * authPolicy = NULL ;
12954+ int sizeMismatch ;
12955+ int policyDiff ;
12956+ word32 cmpSz ;
1290512957
1290612958 /* Find entity's authPolicy by handle type */
1290712959#ifndef FWTPM_NO_NV
@@ -12943,9 +12995,13 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1294312995
1294412996 /* If entity has a non-empty authPolicy, it must match */
1294512997 if (authPolicy != NULL && authPolicy -> size > 0 ) {
12946- if (pSess -> policyDigest .size != authPolicy -> size ||
12947- TPM2_ConstantCompare (pSess -> policyDigest .buffer ,
12948- authPolicy -> buffer , authPolicy -> size ) != 0 ) {
12998+ /* Always run TPM2_ConstantCompare so timing doesn't leak size */
12999+ sizeMismatch = (pSess -> policyDigest .size != authPolicy -> size );
13000+ cmpSz = (pSess -> policyDigest .size < authPolicy -> size ) ?
13001+ pSess -> policyDigest .size : authPolicy -> size ;
13002+ policyDiff = TPM2_ConstantCompare (pSess -> policyDigest .buffer ,
13003+ authPolicy -> buffer , cmpSz );
13004+ if (sizeMismatch | policyDiff ) {
1294913005 #ifdef DEBUG_WOLFTPM
1295013006 printf ("fwTPM: Policy digest mismatch for handle "
1295113007 "0x%x (CC=0x%x)\n" , entityH , cmdCode );
@@ -13072,6 +13128,9 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1307213128 const byte * authVal = NULL ;
1307313129 int authValSz = 0 ;
1307413130 TPM_HANDLE entityH ;
13131+ int sizeMismatch ;
13132+ int hmacDiff ;
13133+ word32 cmpSz ;
1307513134
1307613135 /* Compute cpHash = H(commandCode || handleNames || cpBuffer) */
1307713136 if (FwComputeCpHash (hSess -> authHash , cmdCode ,
@@ -13087,13 +13146,18 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1308713146 FwLookupEntityAuth (ctx , entityH , & authVal , & authValSz );
1308813147
1308913148 /* PolicyPassword with no sessionKey (unsalted/unbound):
13090- * HMAC field contains plaintext authValue per spec Section 19.6.13 */
13149+ * HMAC field contains plaintext authValue per spec Section 19.6.13.
13150+ * Always run TPM2_ConstantCompare so timing doesn't leak auth
13151+ * length match. */
1309113152 if (hSess -> sessionType == TPM_SE_POLICY &&
1309213153 hSess -> isPasswordPolicy &&
1309313154 hSess -> sessionKey .size == 0 ) {
13094- if ((int )cmdAuths [hj ].cmdHmacSize != authValSz ||
13095- TPM2_ConstantCompare (cmdAuths [hj ].cmdHmac ,
13096- authVal , (word32 )authValSz ) != 0 ) {
13155+ sizeMismatch = ((int )cmdAuths [hj ].cmdHmacSize != authValSz );
13156+ cmpSz = (cmdAuths [hj ].cmdHmacSize < (UINT16 )authValSz ) ?
13157+ cmdAuths [hj ].cmdHmacSize : (word32 )authValSz ;
13158+ hmacDiff = TPM2_ConstantCompare (cmdAuths [hj ].cmdHmac ,
13159+ authVal , cmpSz );
13160+ if (sizeMismatch | hmacDiff ) {
1309713161 #ifdef DEBUG_WOLFTPM
1309813162 printf ("fwTPM: PolicyPassword auth failed for handle "
1309913163 "0x%x (CC=0x%x)\n" , entityH , cmdCode );
@@ -13120,9 +13184,13 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1312013184 0 , /* isResponse=0 for command HMAC */
1312113185 expectedHmac , & expectedSz );
1312213186
13123- if (cmdAuths [hj ].cmdHmacSize != (UINT16 )expectedSz ||
13124- TPM2_ConstantCompare (cmdAuths [hj ].cmdHmac ,
13125- expectedHmac , (word32 )expectedSz ) != 0 ) {
13187+ /* Always run TPM2_ConstantCompare so timing doesn't leak size */
13188+ sizeMismatch = (cmdAuths [hj ].cmdHmacSize != (UINT16 )expectedSz );
13189+ cmpSz = (cmdAuths [hj ].cmdHmacSize < (UINT16 )expectedSz ) ?
13190+ cmdAuths [hj ].cmdHmacSize : (word32 )expectedSz ;
13191+ hmacDiff = TPM2_ConstantCompare (cmdAuths [hj ].cmdHmac ,
13192+ expectedHmac , cmpSz );
13193+ if (sizeMismatch | hmacDiff ) {
1312613194 #ifdef DEBUG_WOLFTPM
1312713195 printf ("fwTPM: HMAC session auth failed for handle "
1312813196 "0x%x (CC=0x%x)\n" , entityH , cmdCode );
0 commit comments