diff --git a/src/fwtpm/fwtpm_command.c b/src/fwtpm/fwtpm_command.c index 9a9a25d8..3457948a 100644 --- a/src/fwtpm/fwtpm_command.c +++ b/src/fwtpm/fwtpm_command.c @@ -16811,6 +16811,10 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, else if (entityH == TPM_RH_LOCKOUT) { authPolicy = &ctx->lockoutPolicy; } + /* PCR handles: check PCR_SetAuthPolicy-assigned policy */ + else if (entityH <= PCR_LAST) { + authPolicy = &ctx->pcrPolicy[entityH - PCR_FIRST]; + } /* If entity has a non-empty authPolicy, it must match */ if (authPolicy != NULL && authPolicy->size > 0) { @@ -16870,6 +16874,18 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx, TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); return TPM_RC_SUCCESS; } + else if (authPolicy == NULL) { + /* A policy session cannot authorize a handle whose authPolicy + * cannot be resolved (for example hash/sign sequence handles); + * fail closed per TPM 2.0 Part 1 Sec. 19.7. */ + #ifdef DEBUG_WOLFTPM + printf("fwTPM: Policy session rejected for handle 0x%x with " + "unresolved authPolicy (CC=0x%x)\n", entityH, cmdCode); + #endif + *rspSize = FwBuildErrorResponse(rspBuf, rspCap, + TPM_ST_NO_SESSIONS, TPM_RC_POLICY_FAIL); + return TPM_RC_SUCCESS; + } } } diff --git a/src/fwtpm/fwtpm_crypto.c b/src/fwtpm/fwtpm_crypto.c index 4cdb8e84..6df367fb 100644 --- a/src/fwtpm/fwtpm_crypto.c +++ b/src/fwtpm/fwtpm_crypto.c @@ -572,6 +572,53 @@ TPM_RC FwGenerateEccKey(WC_RNG* rng, /* ================================================================== */ #ifdef HAVE_ECC +/* Constant-time compare of two big-endian byte arrays of equal length. + * Returns 1 when a < b, otherwise 0. */ +static int FwCtLessBE(const byte* a, const byte* b, int len) +{ + int i; + unsigned int borrow = 0; + for (i = len - 1; i >= 0; i--) { + unsigned int diff = (unsigned int)a[i] - (unsigned int)b[i] - borrow; + borrow = (diff >> 8) & 1u; + } + return (int)borrow; +} + +/* Load the curve order into a big-endian, keySz-padded buffer and report its + * bit length, used to bound and mask the derived scalar. */ +static TPM_RC FwEccGetCurveOrder(int wcCurve, byte* orderBuf, int keySz, + int* orderBits) +{ + TPM_RC rc = TPM_RC_SUCCESS; + int idx; + const ecc_set_type* dp; + mp_int order; + + idx = wc_ecc_get_curve_idx(wcCurve); + if (idx < 0) { + return TPM_RC_CURVE; + } + dp = wc_ecc_get_curve_params(idx); + if (dp == NULL) { + return TPM_RC_CURVE; + } + if (mp_init(&order) != MP_OKAY) { + return TPM_RC_FAILURE; + } + if (mp_read_radix(&order, dp->order, MP_RADIX_HEX) != MP_OKAY) { + rc = TPM_RC_FAILURE; + } + if (rc == 0) { + *orderBits = mp_count_bits(&order); + if (mp_to_unsigned_bin_len(&order, orderBuf, keySz) != MP_OKAY) { + rc = TPM_RC_FAILURE; + } + } + mp_clear(&order); + return rc; +} + /* Derive ECC primary key from hierarchy seed per TPM 2.0 Part 1 Section 26.3. * d = KDFa(nameAlg, seed, "ECC", hashUnique, counter, keySz*8) * Q = d * G @@ -596,6 +643,8 @@ TPM_RC FwDeriveEccPrimaryKey(TPMI_ALG_HASH nameAlg, int i; int allZero; volatile byte orAccum; + byte orderBuf[MAX_ECC_BYTES]; + int orderBits = 0; FWTPM_ALLOC_VAR(eccKey, ecc_key); @@ -604,6 +653,12 @@ TPM_RC FwDeriveEccPrimaryKey(TPMI_ALG_HASH nameAlg, return TPM_RC_CURVE; } + rc = FwEccGetCurveOrder(wcCurve, orderBuf, keySz, &orderBits); + if (rc != 0) { + FWTPM_FREE_VAR(eccKey); + return rc; + } + /* Derive private scalar d via KDFa, retry if out of range */ while (!valid && counter < 100) { FwStoreU32BE(counterBuf, counter); @@ -615,14 +670,18 @@ TPM_RC FwDeriveEccPrimaryKey(TPMI_ALG_HASH nameAlg, rc = TPM_RC_FAILURE; break; } - /* Constant-time check d != 0 (all zeros) */ + /* Mask unused high bits so the candidate matches the order bit length */ + if ((orderBits & 7) != 0) { + dBuf[0] &= (byte)((1u << (orderBits & 7)) - 1u); + } + /* Constant-time check 0 < d < order */ orAccum = 0; for (i = 0; i < keySz; i++) { orAccum |= dBuf[i]; } allZero = (orAccum == 0); - if (!allZero) { - valid = 1; /* Accept — range check done by import */ + if (!allZero && FwCtLessBE(dBuf, orderBuf, keySz)) { + valid = 1; } counter++; } diff --git a/src/tpm2.c b/src/tpm2.c index abef32ec..614562c4 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -690,6 +690,14 @@ static inline int TPM2_WolfCrypt_Init(void) { int rc = 0; +#if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ + defined(WOLFSSL_MUTEX_INITIALIZER) + /* gHwLock is statically initialized, so it can guard the reference count + * before wolfCrypt is initialized */ + if (wc_LockMutex(&gHwLock) != 0) + return TPM_RC_FAILURE; +#endif + /* track reference count for wolfCrypt initialization */ if (gWolfCryptRefCount == 0) { #ifdef DEBUG_WOLFSSL @@ -710,8 +718,40 @@ static inline int TPM2_WolfCrypt_Init(void) } gWolfCryptRefCount++; +#if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ + defined(WOLFSSL_MUTEX_INITIALIZER) + wc_UnLockMutex(&gHwLock); +#endif + return rc; } + +static inline void TPM2_WolfCrypt_Cleanup(void) +{ +#if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ + defined(WOLFSSL_MUTEX_INITIALIZER) + int locked = (wc_LockMutex(&gHwLock) == 0); +#endif + + /* track wolf initialize reference count in wolfTPM. wolfCrypt does not + * properly track reference count in v4.1 or older releases */ + gWolfCryptRefCount--; + if (gWolfCryptRefCount < 0) + gWolfCryptRefCount = 0; + if (gWolfCryptRefCount == 0) { + #if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ + !defined(WOLFSSL_MUTEX_INITIALIZER) + wc_FreeMutex(&gHwLock); + #endif + wolfCrypt_Cleanup(); + } + +#if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ + defined(WOLFSSL_MUTEX_INITIALIZER) + if (locked) + wc_UnLockMutex(&gHwLock); +#endif +} #endif /******************************************************************************/ @@ -957,18 +997,7 @@ TPM_RC TPM2_Cleanup(TPM2_CTX* ctx) } #endif - /* track wolf initialize reference count in wolfTPM. wolfCrypt does not - * properly track reference count in v4.1 or older releases */ - gWolfCryptRefCount--; - if (gWolfCryptRefCount < 0) - gWolfCryptRefCount = 0; - if (gWolfCryptRefCount == 0) { - #if !defined(WOLFTPM_NO_LOCK) && !defined(SINGLE_THREADED) && \ - !defined(WOLFSSL_MUTEX_INITIALIZER) - wc_FreeMutex(&gHwLock); - #endif - wolfCrypt_Cleanup(); - } + TPM2_WolfCrypt_Cleanup(); #endif /* !WOLFTPM2_NO_WOLFCRYPT */ #if (defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_LINUX_DEV_AUTODETECT)) \