Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/fwtpm/fwtpm_command.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
}

Expand Down
65 changes: 62 additions & 3 deletions src/fwtpm/fwtpm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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++;
}
Expand Down
53 changes: 41 additions & 12 deletions src/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

/******************************************************************************/
Expand Down Expand Up @@ -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)) \
Expand Down
Loading