@@ -429,6 +429,46 @@ static void FwLookupEntityAuth(FWTPM_CTX* ctx, TPM_HANDLE handle,
429429 }
430430}
431431
432+ /* Constant-time password vs authValue comparison.
433+ * Iterates a fixed upper bound (TPM_MAX_DIGEST_SIZE) with bitwise masks so
434+ * neither the trip count nor per-iteration work depends on the secret
435+ * authValSz. Trailing zeros on either side are treated as insignificant
436+ * (matches TCG reference for authValues padded to nameAlg digest size).
437+ * Returns 1 on mismatch, 0 on match. Precondition: pwSz and avSz must
438+ * each be <= TPM_MAX_DIGEST_SIZE; out-of-range inputs fail closed. */
439+ static int FwCtAuthCompare (const byte * password , int pwSz ,
440+ const byte * authVal , int avSz )
441+ {
442+ byte zeroAuth [TPM_MAX_DIGEST_SIZE ];
443+ const byte * avPtr ;
444+ volatile byte diff = 0 ;
445+ int ci ;
446+
447+ if (pwSz < 0 || avSz < 0 ||
448+ pwSz > TPM_MAX_DIGEST_SIZE || avSz > TPM_MAX_DIGEST_SIZE ) {
449+ return 1 ;
450+ }
451+
452+ XMEMSET (zeroAuth , 0 , sizeof (zeroAuth ));
453+ avPtr = (authVal != NULL ) ? authVal : zeroAuth ;
454+
455+ for (ci = 0 ; ci < TPM_MAX_DIGEST_SIZE ; ci ++ ) {
456+ /* 0xFF if ci < bound, else 0x00. Use UINT32 (guaranteed 32-bit
457+ * wolfTPM typedef) so the >> 31 shift is always well-defined. */
458+ byte pwMask = (byte )- ((UINT32 )(ci - pwSz ) >> 31 );
459+ byte avMask = (byte )- ((UINT32 )(ci - avSz ) >> 31 );
460+ byte overlap = (byte )(pwMask & avMask );
461+ /* Overlap region: bytes must match */
462+ diff |= (byte )((password [ci ] ^ avPtr [ci ]) & overlap );
463+ /* Trailing bytes of pw past avSz must be zero */
464+ diff |= (byte )(password [ci ] & (pwMask & (byte )~avMask ));
465+ /* Trailing bytes of av past pwSz must be zero */
466+ diff |= (byte )(avPtr [ci ] & (avMask & (byte )~pwMask ));
467+ }
468+
469+ return ((int )diff != 0 ) ? 1 : 0 ;
470+ }
471+
432472/* Compute cpHash = H(commandCode || name1 || ... || cpBuffer)
433473 * Per TPM 2.0 Part 1 Section 18.7 */
434474static int FwComputeCpHash (TPMI_ALG_HASH hashAlg , TPM_CC cmdCode ,
@@ -9975,6 +10015,7 @@ static TPM_RC FwCmd_NV_DefineSpace(FWTPM_CTX* ctx, TPM2_Packet* cmd,
997510015 FwRspNoParams (rsp , cmdTag );
997610016 }
997710017
10018+ TPM2_ForceZero (& auth , sizeof (auth ));
997810019 return rc ;
997910020}
998010021
@@ -12719,9 +12760,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1271912760 int doEncRsp = 0 ; /* Encrypt outgoing response param */
1272012761#endif
1272112762 int pj , hj ; /* Loop indices for auth validation */
12722- int pwSz , avSz , maxSz , minSz , authFail ; /* Password comparison */
12723- volatile byte diff ;
12724- int ci ;
12763+ int authFail ; /* Password comparison result */
1272512764
1272612765 if (ctx == NULL || cmdBuf == NULL || rspBuf == NULL || rspSize == NULL ) {
1272712766 return BAD_FUNC_ARG ;
@@ -13085,29 +13124,8 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
1308513124
1308613125 FwLookupEntityAuth (ctx , entityH , & authVal , & authValSz );
1308713126
13088- /* Compare password with authValue in constant time.
13089- * Per TCG reference implementation, trailing zeros are
13090- * insignificant (handles authValues padded to nameAlg
13091- * digest size). We compare up to the max of both sizes
13092- * and verify trailing bytes are zero, all in constant
13093- * time to avoid leaking the effective auth length. */
13094- diff = 0 ;
13095- pwSz = (int )cmdAuths [pj ].passwordSize ;
13096- avSz = authValSz ;
13097- maxSz = (pwSz > avSz ) ? pwSz : avSz ;
13098- minSz = (pwSz < avSz ) ? pwSz : avSz ;
13099- /* Compare overlapping portion */
13100- for (ci = 0 ; ci < minSz ; ci ++ ) {
13101- diff |= cmdAuths [pj ].password [ci ] ^ authVal [ci ];
13102- }
13103- /* Verify trailing bytes of the longer buffer are zero */
13104- for (ci = minSz ; ci < maxSz ; ci ++ ) {
13105- if (ci < pwSz )
13106- diff |= cmdAuths [pj ].password [ci ];
13107- if (ci < avSz )
13108- diff |= authVal [ci ];
13109- }
13110- authFail = ((int )diff != 0 );
13127+ authFail = FwCtAuthCompare (cmdAuths [pj ].password ,
13128+ (int )cmdAuths [pj ].passwordSize , authVal , authValSz );
1311113129 if (authFail ) {
1311213130 #ifdef DEBUG_WOLFTPM
1311313131 printf ("fwTPM: Password auth failed for handle "
0 commit comments