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
14 changes: 14 additions & 0 deletions .github/workflows/make-test-swtpm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ jobs:
needs_dist: true
needs_install: true

# wolfSSL without timing resistance (--disable-harden)
- name: no-harden
wolfssl_config: --enable-wolftpm --enable-pkcallbacks --disable-harden
test_command: "make check && WOLFSSL_PATH=./wolfssl ./examples/run_examples.sh"
Comment thread
aidangarske marked this conversation as resolved.

# CSharp wrapper tests
- name: csharp
test_command: "true"
Expand Down Expand Up @@ -133,6 +138,15 @@ jobs:
wolfssl_config: --enable-wolftpm --enable-ecc --enable-sha384 --enable-aesgcm --enable-hkdf --enable-sp
wolftpm_config: --enable-spdm --enable-nations --enable-smallstack --disable-fwtpm
needs_swtpm: false
# SPDM vendors with wolfSSL without timing resistance (compile-only)
- name: spdm-nuvoton-no-harden
wolfssl_config: --enable-wolftpm --enable-ecc --enable-sha384 --enable-aesgcm --enable-hkdf --enable-sp --disable-harden
wolftpm_config: --enable-spdm --enable-nuvoton --disable-fwtpm
needs_swtpm: false
- name: spdm-nations-no-harden
wolfssl_config: --enable-wolftpm --enable-ecc --enable-sha384 --enable-aesgcm --enable-hkdf --enable-sp --disable-harden
wolftpm_config: --enable-spdm --enable-nations --disable-fwtpm
needs_swtpm: false
# Microchip
- name: microchip
wolftpm_config: --enable-microchip --disable-fwtpm
Expand Down
29 changes: 6 additions & 23 deletions src/tpm2_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1586,8 +1586,7 @@ int wolfTPM2_SpdmConnectNuvoton(WOLFTPM2_DEV* dev,
return rc;
}
}
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
defined(ECC_TIMING_RESISTANT)
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
else {
/* Auto-generate ephemeral P-384 key pair for mutual authentication */
ecc_key hostKey;
Expand Down Expand Up @@ -1677,11 +1676,6 @@ int wolfTPM2_SpdmConnectNuvoton(WOLFTPM2_DEV* dev,
tpmtPub, (word32)(p - tpmtPub));
if (rc != 0) return rc;
}
#elif !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
else {
/* Requester key auto-generation requires timing-resistant ECC */
return NOT_COMPILED_IN;
}
#endif /* !WOLFTPM2_NO_WOLFCRYPT && HAVE_ECC */

/* Perform the Nuvoton SPDM handshake */
Expand Down Expand Up @@ -1780,8 +1774,7 @@ int wolfTPM2_SpdmConnectNations(WOLFTPM2_DEV* dev,
return rc;
}
}
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
defined(ECC_TIMING_RESISTANT)
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
else {
/* Auto-generate ephemeral P-384 key pair for mutual authentication.
* Nations: GIVE_PUB is not supported, but MUT_AUTH is still required.
Expand Down Expand Up @@ -1859,11 +1852,6 @@ int wolfTPM2_SpdmConnectNations(WOLFTPM2_DEV* dev,
tpmtPub, (word32)(p - tpmtPub));
if (rc != 0) return rc;
}
#elif !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
else {
/* Requester key auto-generation requires timing-resistant ECC */
return NOT_COMPILED_IN;
}
#endif /* !WOLFTPM2_NO_WOLFCRYPT && HAVE_ECC */

/* Perform the TCG SPDM handshake */
Expand Down Expand Up @@ -2409,8 +2397,7 @@ int wolfTPM2_Cleanup(WOLFTPM2_DEV* dev)
}

#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
!defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP) && \
defined(ECC_TIMING_RESISTANT)
!defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP)
/* TPM2_KDFe is now in tpm2_param_enc.c (shared with fwTPM) */

#ifdef ALT_ECC_SIZE
Expand Down Expand Up @@ -2793,8 +2780,7 @@ int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpmKey,

#ifndef WOLFTPM2_NO_WOLFCRYPT
switch (tpmKey->pub.publicArea.type) {
#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \
defined(WOLFSSL_PUBLIC_MP) && defined(ECC_TIMING_RESISTANT)
#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP)
case TPM_ALG_ECC:
rc = wolfTPM2_EncryptSecret_ECC(dev, tpmKey, data, secret, label);
break;
Expand Down Expand Up @@ -5320,11 +5306,8 @@ static int wolfTPM2_EccMakePubBlinded(ecc_key* key, ecc_point* point)
TPM2_ForceZero(&rng, sizeof(rng));
return rc;
#else
(void)key;
(void)point;
/* Private-only imports require blinded scalar multiplication. Callers
* must provide the public point when that protection is unavailable. */
return NOT_COMPILED_IN;
/* blinding requires ECC_TIMING_RESISTANT in wolfCrypt */
return wc_ecc_make_pub(key, point);
#endif
}

Expand Down
97 changes: 97 additions & 0 deletions tests/unit_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -2958,6 +2958,11 @@ static void test_wolfTPM2_EncryptSecret(void)
WOLFTPM2_KEY tpmKey;
TPM2B_DATA data;
TPM2B_ENCRYPTED_SECRET secret;
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
!defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP)
WOLFTPM2_KEY eccKey;
const TPMT_PUBLIC* eccPub;
#endif
#if defined(WOLFTPM_MLKEM) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \
(defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \
defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024))
Expand Down Expand Up @@ -2988,6 +2993,29 @@ static void test_wolfTPM2_EncryptSecret(void)
rc = wolfTPM2_EncryptSecret(&dev, &tpmKey, &data, NULL, "SECRET");
AssertIntEQ(rc, BAD_FUNC_ARG);

#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
!defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP)
/* ECC path: the salt is the KDFe output (nameAlg digest size) and the
* ephemeral public point (x and y, each size prefixed) goes on the wire.
* Must work with or without ECC_TIMING_RESISTANT in wolfCrypt. */
XMEMSET(&eccKey, 0, sizeof(eccKey));
XMEMSET(&data, 0, sizeof(data));
XMEMSET(&secret, 0, sizeof(secret));

rc = wolfTPM2_CreateSRK(&dev, &eccKey, TPM_ALG_ECC, NULL, 0);
AssertIntEQ(rc, 0);
eccPub = &eccKey.pub.publicArea;

rc = wolfTPM2_EncryptSecret(&dev, &eccKey, &data, &secret, "SECRET");
AssertIntEQ(rc, 0);
AssertIntEQ(data.size, TPM2_GetHashDigestSize(eccPub->nameAlg));
AssertIntEQ(secret.size, 2 * ((int)sizeof(UINT16) +
TPM2_GetCurveSize(eccPub->parameters.eccDetail.curveID)));
printf("Test TPM Wrapper: %-40s Passed\n", "EncryptSecret ECC:");

wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
#endif

#if defined(WOLFTPM_MLKEM) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \
(defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_KYBER512) || \
defined(WOLFSSL_KYBER768) || defined(WOLFSSL_KYBER1024))
Expand Down Expand Up @@ -8785,6 +8813,74 @@ static void test_wolfTPM2_ImportEccPrivateKeySeed_ErrorPaths(void)
}
#endif /* HAVE_ECC */

/* A private-only wolf ECC key has no public point, so creating the key blob
* derives it from the private scalar. Must work with or without
* ECC_TIMING_RESISTANT in wolfCrypt. */
static void test_wolfTPM2_CreateEccKeyBlob_PrivateOnly(void)
{
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \
!defined(NO_ECC256) && !defined(WC_NO_RNG) && \
defined(WOLFSSL_PUBLIC_MP) && defined(WOLFSSL_AES_CFB)
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY srk;
WOLFTPM2_KEYBLOB keyBlob;
WC_RNG rng;
ecc_key privKey, refKey;
const TPMS_ECC_POINT* pt;
byte d[32], qx[32], qy[32];
word32 qxSz = sizeof(qx), qySz = sizeof(qy);

XMEMSET(&srk, 0, sizeof(srk));
XMEMSET(&keyBlob, 0, sizeof(keyBlob));

rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
AssertIntEQ(rc, 0);
rc = wolfTPM2_CreateSRK(&dev, &srk, TPM_ALG_ECC, NULL, 0);
AssertIntEQ(rc, 0);

/* random scalar below the P-256 order and not zero */
AssertIntEQ(wc_InitRng(&rng), 0);
AssertIntEQ(wc_RNG_GenerateBlock(&rng, d, sizeof(d)), 0);
d[0] &= 0x7F;
d[sizeof(d) - 1] |= 0x01;

/* reference public point for the same scalar */
AssertIntEQ(wc_ecc_init(&refKey), 0);
AssertIntEQ(wc_ecc_import_private_key_ex(d, sizeof(d), NULL, 0, &refKey,
ECC_SECP256R1), 0);
AssertIntEQ(wc_ecc_make_pub(&refKey, NULL), 0);
AssertIntEQ(wc_ecc_export_public_raw(&refKey, qx, &qxSz, qy, &qySz), 0);

AssertIntEQ(wc_ecc_init(&privKey), 0);
AssertIntEQ(wc_ecc_import_private_key_ex(d, sizeof(d), NULL, 0, &privKey,
ECC_SECP256R1), 0);
AssertIntEQ(privKey.type, ECC_PRIVATEKEY_ONLY);

rc = wolfTPM2_CreateEccKeyBlob(&dev, &srk, &privKey, &keyBlob);
AssertIntEQ(rc, 0);
pt = &keyBlob.pub.publicArea.unique.ecc;
AssertIntEQ(pt->x.size, (int)qxSz);
AssertIntEQ(pt->y.size, (int)qySz);
AssertIntEQ(XMEMCMP(pt->x.buffer, qx, qxSz), 0);
AssertIntEQ(XMEMCMP(pt->y.buffer, qy, qySz), 0);

rc = wolfTPM2_LoadKey(&dev, &keyBlob, &srk.handle);
AssertIntEQ(rc, 0);

wolfTPM2_UnloadHandle(&dev, &keyBlob.handle);
wolfTPM2_UnloadHandle(&dev, &srk.handle);
wc_ecc_free(&privKey);
wc_ecc_free(&refKey);
wc_FreeRng(&rng);
wc_ForceZero(d, sizeof(d));
wolfTPM2_Cleanup(&dev);

printf("Test TPM Wrapper:\tCreateEccKeyBlob private only:\tPassed\n");
#endif
}

#ifndef NO_RSA
static void test_wolfTPM2_ImportRsaPrivateKeySeed_ErrorPaths(void)
{
Expand Down Expand Up @@ -9982,6 +10078,7 @@ int unit_tests(int argc, char *argv[])
#ifdef HAVE_ECC
test_wolfTPM2_ImportEccPrivateKeySeed_ErrorPaths();
#endif
test_wolfTPM2_CreateEccKeyBlob_PrivateOnly();
#ifndef NO_RSA
test_wolfTPM2_ImportRsaPrivateKeySeed_ErrorPaths();
#endif
Expand Down
Loading