Skip to content
Open
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
14 changes: 14 additions & 0 deletions src/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -7034,6 +7034,20 @@ int TPM2_GetCurveSize(TPM_ECC_CURVE curveID)
return 0;
}

TPM_ALG_ID TPM2_GetCurveHashAlg(TPM_ECC_CURVE curveID)
Comment thread
dgarske marked this conversation as resolved.
{
int curveSz = TPM2_GetCurveSize(curveID);

Comment thread
dgarske marked this conversation as resolved.
/* Pair the message digest strength to the curve size, matching the TCG
* recommended curve/hash combinations (P256/SHA256, P384/SHA384,
* P521/SHA512). */
if (curveSz >= 64) /* P521 (66), BP512 (64) */
return TPM_ALG_SHA512;
if (curveSz == 48) /* P384, BP384 */
return TPM_ALG_SHA384;
return TPM_ALG_SHA256; /* P256 and smaller */
}

int TPM2_GetTpmCurve(int curve_id)
{
int ret = -1;
Expand Down
12 changes: 5 additions & 7 deletions src/tpm2_cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,13 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
TPMT_PUBLIC publicTemplate;
TPMI_ALG_HASH hashAlg;

if (curve_id == TPM_ECC_NIST_P521)
hashAlg = TPM_ALG_SHA512;
else if (curve_id == TPM_ECC_NIST_P384)
hashAlg = TPM_ALG_SHA384;
else
hashAlg = TPM_ALG_SHA256;
hashAlg = TPM2_GetCurveHashAlg(curve_id);
Comment thread
dgarske marked this conversation as resolved.

XMEMSET(&publicTemplate, 0, sizeof(publicTemplate));
rc = wolfTPM2_GetKeyTemplate_ECC_ex(&publicTemplate, hashAlg,
/* Use the internal helper (not the public _ex wrapper) so
* the curve wolfCrypt negotiated is honored exactly and is
* not remapped by WOLFTPM2_ECC_DEFAULT_CURVE. */
rc = GetKeyTemplateECC(&publicTemplate, hashAlg,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
curve_id, TPM_ALG_ECDSA, hashAlg);
Expand Down
73 changes: 61 additions & 12 deletions src/tpm2_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -8224,20 +8224,32 @@ int GetKeyTemplateECC(TPMT_PUBLIC* publicTemplate,
TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve,
TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash)
{
int curveSz = TPM2_GetCurveSize(curve);
int curveSz;

if (publicTemplate == NULL || curveSz == 0)
if (publicTemplate == NULL)
return BAD_FUNC_ARG;

#if defined(NO_ECC256) && defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
/* make sure we use a curve that is enabled */
#ifdef NO_ECC256
/* P256 is compiled out of wolfCrypt; substitute the configured (enabled)
* default curve so callers requesting P256 still get a usable curve. This
* is availability-driven and applies to every caller (including the named
* EK/SRK/AIK templates) because the build simply cannot honor P256. The
* configurable default-curve preference lives in the public ECC template
* wrappers, not here, so explicit curves through this helper are honored. */
if (curve == TPM_ECC_NIST_P256) {
curve = TPM_ECC_NIST_P384;
nameAlg = TPM_ALG_SHA384;
sigHash = TPM_ALG_SHA384;
curve = WOLFTPM2_ECC_DEFAULT_CURVE;
nameAlg = TPM2_GetCurveHashAlg(curve);
Comment thread
dgarske marked this conversation as resolved.
if (sigHash != TPM_ALG_NULL)
sigHash = nameAlg;
}
#endif

/* Compute curve size after any substitution so coordinate sizes and the
* AES wrap strength below match the curve actually used. */
curveSz = TPM2_GetCurveSize(curve);
if (curveSz == 0)
return BAD_FUNC_ARG;

XMEMSET(publicTemplate, 0, sizeof(TPMT_PUBLIC));
publicTemplate->type = TPM_ALG_ECC;
publicTemplate->nameAlg = nameAlg;
Expand Down Expand Up @@ -8280,18 +8292,45 @@ int wolfTPM2_GetKeyTemplate_RSA(TPMT_PUBLIC* publicTemplate,
TPM_ALG_NULL, WOLFTPM2_WRAP_DIGEST);
}

/* Resolve a P256 "use the library default" request to the build-configured
* WOLFTPM2_ECC_DEFAULT_CURVE, pairing the name/sig hash via
* TPM2_GetCurveHashAlg. No-op when the default is P256 (the shipped default),
* so existing builds are unchanged. This lets a build make P384 (or another
* curve) the wrapper default - e.g. wolfTPM2_CreateSRK(TPM_ALG_ECC) - without
* editing call sites. The EK index templates (TCG-fixed curve and auth policy),
* the explicit-curve IAK/IDevID helpers, and the crypto callback (curve
* negotiated by wolfCrypt) intentionally do NOT use this and keep their exact
* curve. */
static void wolfTPM2_ResolveDefaultEccCurve(TPM_ECC_CURVE* curve,
TPM_ALG_ID* nameAlg, TPM_ALG_ID* sigHash)
{
if (*curve == TPM_ECC_NIST_P256 &&
WOLFTPM2_ECC_DEFAULT_CURVE != TPM_ECC_NIST_P256) {
*curve = WOLFTPM2_ECC_DEFAULT_CURVE;
if (nameAlg != NULL)
*nameAlg = TPM2_GetCurveHashAlg(*curve);
if (sigHash != NULL && *sigHash != TPM_ALG_NULL)
*sigHash = TPM2_GetCurveHashAlg(*curve);
}
}

int wolfTPM2_GetKeyTemplate_ECC_ex(TPMT_PUBLIC* publicTemplate,
TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve,
TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash)
{
/* General-purpose ECC template API: a P256 request follows the configured
* default curve. */
wolfTPM2_ResolveDefaultEccCurve(&curve, &nameAlg, &sigHash);
return GetKeyTemplateECC(publicTemplate, nameAlg,
objectAttributes, curve, sigScheme, sigHash);
}

int wolfTPM2_GetKeyTemplate_ECC(TPMT_PUBLIC* publicTemplate,
TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve, TPM_ALG_ID sigScheme)
{
return GetKeyTemplateECC(publicTemplate, WOLFTPM2_WRAP_DIGEST,
/* Route through the _ex wrapper so the configurable default curve applies
* to this general-purpose API as well. */
return wolfTPM2_GetKeyTemplate_ECC_ex(publicTemplate, WOLFTPM2_WRAP_DIGEST,
objectAttributes, curve, sigScheme, WOLFTPM2_WRAP_DIGEST);
}

Expand Down Expand Up @@ -8541,13 +8580,17 @@ int wolfTPM2_GetKeyTemplate_RSA_SRK(TPMT_PUBLIC* publicTemplate)

int wolfTPM2_GetKeyTemplate_ECC_SRK(TPMT_PUBLIC* publicTemplate)
{
TPM_ECC_CURVE curve = TPM_ECC_NIST_P256;
TPM_ALG_ID nameAlg = TPM_ALG_SHA256;
TPMA_OBJECT objectAttributes = (
TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent |
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_restricted | TPMA_OBJECT_decrypt | TPMA_OBJECT_noDA);

return GetKeyTemplateECC(publicTemplate, TPM_ALG_SHA256,
objectAttributes, TPM_ECC_NIST_P256, TPM_ALG_NULL, TPM_ALG_NULL);
/* Storage primary defaults to P256 but follows WOLFTPM2_ECC_DEFAULT_CURVE. */
wolfTPM2_ResolveDefaultEccCurve(&curve, &nameAlg, NULL);
return GetKeyTemplateECC(publicTemplate, nameAlg,
objectAttributes, curve, TPM_ALG_NULL, TPM_ALG_NULL);
}

int wolfTPM2_GetKeyTemplate_RSA_AIK(TPMT_PUBLIC* publicTemplate)
Expand All @@ -8569,13 +8612,19 @@ int wolfTPM2_GetKeyTemplate_RSA_AIK(TPMT_PUBLIC* publicTemplate)
int wolfTPM2_GetKeyTemplate_ECC_AIK(TPMT_PUBLIC* publicTemplate)
{
int ret;
TPM_ECC_CURVE curve = TPM_ECC_NIST_P256;
TPM_ALG_ID nameAlg = TPM_ALG_SHA256;
TPM_ALG_ID sigHash = TPM_ALG_SHA256;
TPMA_OBJECT objectAttributes = (
TPMA_OBJECT_fixedTPM | TPMA_OBJECT_fixedParent |
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_restricted | TPMA_OBJECT_sign | TPMA_OBJECT_noDA);

ret = GetKeyTemplateECC(publicTemplate, TPM_ALG_SHA256,
objectAttributes, TPM_ECC_NIST_P256, TPM_ALG_ECDSA, TPM_ALG_SHA256);
/* Attestation signing key defaults to P256 but follows the configured
* default curve. */
wolfTPM2_ResolveDefaultEccCurve(&curve, &nameAlg, &sigHash);
ret = GetKeyTemplateECC(publicTemplate, nameAlg,
objectAttributes, curve, TPM_ALG_ECDSA, sigHash);
if (ret == 0) {
publicTemplate->parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
}
Expand Down
58 changes: 58 additions & 0 deletions tests/unit_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -2538,10 +2538,67 @@ static void test_TPM2_BrainpoolCurveMapping(void)
AssertIntEQ(TPM2_GetCurveSize(TPM_ECC_BP_P384_R1), 48);
AssertIntEQ(TPM2_GetCurveSize(TPM_ECC_BP_P512_R1), 64);

/* TPM2_GetCurveHashAlg pairs the digest strength to the curve size,
* per TCG recommended combinations. */
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_NIST_P256), TPM_ALG_SHA256);
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_NIST_P384), TPM_ALG_SHA384);
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_NIST_P521), TPM_ALG_SHA512);
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_BP_P256_R1), TPM_ALG_SHA256);
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_BP_P384_R1), TPM_ALG_SHA384);
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_BP_P512_R1), TPM_ALG_SHA512); /* 64 -> SHA512 */
AssertIntEQ(TPM2_GetCurveHashAlg(TPM_ECC_BN_P638), TPM_ALG_SHA512);

printf("Test TPM Wrapper:\tBrainpool curve mapping:\tPassed\n");
#endif
}

/* The P256-defaulting wrapper templates (general ECC, SRK, AIK) follow the
* build's WOLFTPM2_ECC_DEFAULT_CURVE: a no-op in the shipped P256 build, an
* upgrade when overridden to e.g. P384. The EK templates are TCG-fixed and keep
* their exact curve and policy (except under NO_ECC256, where P256 is
* unavailable to every caller - the EK checks are guarded for that case). */
static void test_TPM2_EccDefaultCurveTemplate(void)
{
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
TPMT_PUBLIC t;

/* P256 through the general API follows the configured default + paired
* hash. In an overridden build this proves the upgrade; in the default
* P256 build it is a no-op. */
AssertIntEQ(wolfTPM2_GetKeyTemplate_ECC(&t, TPMA_OBJECT_sign,
TPM_ECC_NIST_P256, TPM_ALG_ECDSA), 0);
AssertIntEQ(t.parameters.eccDetail.curveID, WOLFTPM2_ECC_DEFAULT_CURVE);
AssertIntEQ(t.nameAlg, TPM2_GetCurveHashAlg(WOLFTPM2_ECC_DEFAULT_CURVE));

/* The storage primary (wolfTPM2_CreateSRK ECC path) follows the default. */
AssertIntEQ(wolfTPM2_GetKeyTemplate_ECC_SRK(&t), 0);
AssertIntEQ(t.parameters.eccDetail.curveID, WOLFTPM2_ECC_DEFAULT_CURVE);
AssertIntEQ(t.nameAlg, TPM2_GetCurveHashAlg(WOLFTPM2_ECC_DEFAULT_CURVE));

/* The attestation signing key (AIK) follows the default. This block
* exercises the sigHash arg of the resolver, so lock in name and sig
* hash too. */
AssertIntEQ(wolfTPM2_GetKeyTemplate_ECC_AIK(&t), 0);
AssertIntEQ(t.parameters.eccDetail.curveID, WOLFTPM2_ECC_DEFAULT_CURVE);
AssertIntEQ(t.nameAlg, TPM2_GetCurveHashAlg(WOLFTPM2_ECC_DEFAULT_CURVE));
AssertIntEQ(t.parameters.eccDetail.scheme.details.ecdsa.hashAlg,
TPM2_GetCurveHashAlg(WOLFTPM2_ECC_DEFAULT_CURVE));

#ifndef NO_ECC256
/* EK P256 NV index is TCG-fixed and must NOT follow the default curve.
* Skipped under NO_ECC256: there GetKeyTemplateECC substitutes P256 for an
* enabled curve for every caller, including the EK, because the build
* cannot honor P256 at all. */
AssertIntEQ(wolfTPM2_GetKeyTemplate_EKIndex(TPM2_NV_EK_ECC_P256, &t), 0);
AssertIntEQ(t.parameters.eccDetail.curveID, TPM_ECC_NIST_P256);
AssertIntEQ(t.nameAlg, TPM_ALG_SHA256);
AssertIntEQ(t.authPolicy.size, sizeof(TPM_20_EK_AUTH_POLICY));
#endif

printf("Test TPM Wrapper:\tECC default-curve template:\tPassed\n");
#endif
}

static void test_TPM2_KeyedHashScheme_XorSerialize(void)
{
TPM2_Packet packet;
Expand Down Expand Up @@ -4965,6 +5022,7 @@ int unit_tests(int argc, char *argv[])
test_TPM2_ParsePoint_OuterResync();
test_TPM2_ParseSignature_NullAlg();
test_TPM2_BrainpoolCurveMapping();
test_TPM2_EccDefaultCurveTemplate();
test_wolfTPM2_RsaEncryptDecrypt_OversizedBufferE();
test_wolfTPM2_SignHashScheme_DigestSize();
test_wolfTPM2_VerifyHashTicket_DigestSize();
Expand Down
13 changes: 13 additions & 0 deletions wolftpm/tpm2.h
Original file line number Diff line number Diff line change
Expand Up @@ -4122,6 +4122,19 @@ WOLFTPM_API const char* TPM2_GetHierarchyDesc(TPMI_RH_HIERARCHY_AUTH authHandle)
*/
WOLFTPM_API int TPM2_GetCurveSize(TPM_ECC_CURVE curveID);

/*!
\ingroup TPM2_Proprietary
\brief Determine the recommended message digest for a TPM ECC Curve

\return TPM_ALG_ID of the hash paired to the curve size (P256->SHA256,
P384->SHA384, P521->SHA512). Defaults to TPM_ALG_SHA256.

\param curveID value of type TPM_ECC_CURVE

\sa TPM2_GetCurveSize
*/
WOLFTPM_API TPM_ALG_ID TPM2_GetCurveHashAlg(TPM_ECC_CURVE curveID);

/*!
\ingroup TPM2_Proprietary
\brief Translate a wolfcrypt curve type to its corresponding TPM curve type
Expand Down
25 changes: 25 additions & 0 deletions wolftpm/tpm2_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,31 @@ typedef int64_t INT64;
#define WOLFTPM2_WRAP_ECC_KEY_BITS (MAX_ECC_KEY_BITS*8)
#endif

/* Defines the library-default ECC curve used by the wrapper key templates that
* default to P256: wolfTPM2_GetKeyTemplate_ECC[_ex] and the storage/attestation
* primaries (wolfTPM2_GetKeyTemplate_ECC_SRK / _AIK, used by
* wolfTPM2_CreateSRK(TPM_ALG_ECC)). A P256 request through these follows this
* default, so a build can opt in to a stronger default (e.g. P384) without
* editing call sites. Override at build time, e.g.
* -DWOLFTPM2_ECC_DEFAULT_CURVE=TPM_ECC_NIST_P384. The matching name/sig hash is
* derived from the curve via TPM2_GetCurveHashAlg, so only the curve needs to
* be set. When left at the default of P256 the behavior is unchanged. The EK
* templates (TCG-fixed curve and auth policy), the explicit-curve IAK/IDevID
* helpers, and crypto-callback keys (curve negotiated by wolfCrypt) keep their
* exact curve. If P256 is compiled out (NO_ECC256) the default falls back to an
* enabled curve. */
#ifndef WOLFTPM2_ECC_DEFAULT_CURVE
#if !defined(NO_ECC256)
#define WOLFTPM2_ECC_DEFAULT_CURVE TPM_ECC_NIST_P256
#elif defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
#define WOLFTPM2_ECC_DEFAULT_CURVE TPM_ECC_NIST_P384
#elif defined(HAVE_ECC521) && ECC_MIN_KEY_SZ <= 521
#define WOLFTPM2_ECC_DEFAULT_CURVE TPM_ECC_NIST_P521
#else
#define WOLFTPM2_ECC_DEFAULT_CURVE TPM_ECC_NIST_P256
#endif
#endif
Comment thread
dgarske marked this conversation as resolved.

#if !defined(WOLFTPM2_NO_WOLFCRYPT) && \
(defined(WOLF_CRYPTO_DEV) || defined(WOLF_CRYPTO_CB))
/* Enable the crypto callback support */
Expand Down
4 changes: 2 additions & 2 deletions wolftpm/tpm2_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -3490,7 +3490,7 @@ WOLFTPM_API int wolfTPM2_GetKeyTemplate_RSA_ex(TPMT_PUBLIC* publicTemplate,

\param publicTemplate pointer to an empty structure of TPMT_PUBLIC type, to store the new ECC key template
\param objectAttributes integer value of TPMA_OBJECT type, can contain one or more attributes, e.g. TPMA_OBJECT_fixedTPM
\param curve integer value of TPM_ECC_CURVE type, specifying a TPM supported ECC curve ID
\param curve integer value of TPM_ECC_CURVE type, specifying a TPM supported ECC curve ID; a TPM_ECC_NIST_P256 request follows the build-configured WOLFTPM2_ECC_DEFAULT_CURVE (with its matching hash), other curves are used as given
\param sigScheme integer value of TPM_ALG_ID type, specifying a TPM supported signature scheme

\sa wolfTPM2_GetKeyTemplate_ECC_ex
Expand All @@ -3512,7 +3512,7 @@ WOLFTPM_API int wolfTPM2_GetKeyTemplate_ECC(TPMT_PUBLIC* publicTemplate,
\param publicTemplate pointer to an empty structure of TPMT_PUBLIC type, to store the new ECC key template
\param nameAlg integer value of TPM_ALG_ID type, specifying a TPM supported hashing algorithm, typically TPM_ALG_SHA256 for SHA 256
\param objectAttributes integer value of TPMA_OBJECT type, can contain one or more attributes, e.g. TPMA_OBJECT_fixedTPM
\param curve integer value of TPM_ECC_CURVE type, specifying a TPM supported ECC curve ID
\param curve integer value of TPM_ECC_CURVE type, specifying a TPM supported ECC curve ID; a TPM_ECC_NIST_P256 request follows the build-configured WOLFTPM2_ECC_DEFAULT_CURVE (with its matching hash), other curves are used as given
\param sigScheme integer value of TPM_ALG_ID type, specifying a TPM supported signature scheme
\param sigHash integer value of TPM_ALG_ID type, specifying a TPM supported signature hash scheme

Expand Down
Loading