6746 - Right-align short ECC coordinates in wolfTPM2_EccKey_TpmToWolf

pull/547/head
aidan garske 2026-07-07 13:26:00 -07:00
parent 9a56a4632d
commit ee00c70468
2 changed files with 78 additions and 6 deletions

View File

@ -4799,7 +4799,7 @@ int wolfTPM2_RsaKey_PubPemToTpm(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
int wolfTPM2_EccKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
ecc_key* wolfKey)
{
int rc, curve_id;
int rc, curve_id, keySz;
byte qx[WOLFTPM2_WRAP_ECC_KEY_BITS / 8];
byte qy[WOLFTPM2_WRAP_ECC_KEY_BITS / 8];
word32 qxSz;
@ -4813,24 +4813,32 @@ int wolfTPM2_EccKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
/* load curve type */
curve_id = tpmKey->pub.publicArea.parameters.eccDetail.curveID;
keySz = wolfTPM2_GetCurveSize(curve_id); /* field size for right-align */
rc = TPM2_GetWolfCurve(curve_id);
if (rc < 0)
return rc;
curve_id = rc;
if (keySz <= 0 || keySz > (int)sizeof(qx)) {
return BUFFER_E;
}
/* load public key */
/* load public key; right-align each coordinate into the field-size buffer
* so wc_ecc_import_unsigned reads the correct big-endian value even when
* the TPM stripped leading zero bytes */
qxSz = tpmKey->pub.publicArea.unique.ecc.x.size;
if (qxSz > sizeof(qx) ||
if (qxSz > (word32)keySz ||
qxSz > sizeof(tpmKey->pub.publicArea.unique.ecc.x.buffer)) {
return BUFFER_E;
}
XMEMCPY(qx, tpmKey->pub.publicArea.unique.ecc.x.buffer, qxSz);
XMEMCPY(qx + (keySz - (int)qxSz),
tpmKey->pub.publicArea.unique.ecc.x.buffer, qxSz);
qySz = tpmKey->pub.publicArea.unique.ecc.y.size;
if (qySz > sizeof(qy) ||
if (qySz > (word32)keySz ||
qySz > sizeof(tpmKey->pub.publicArea.unique.ecc.y.buffer)) {
return BUFFER_E;
}
XMEMCPY(qy, tpmKey->pub.publicArea.unique.ecc.y.buffer, qySz);
XMEMCPY(qy + (keySz - (int)qySz),
tpmKey->pub.publicArea.unique.ecc.y.buffer, qySz);
/* load public key portion into wolf ecc_key */
rc = wc_ecc_import_unsigned(wolfKey, qx, qy, NULL, curve_id);

View File

@ -2695,6 +2695,69 @@ static void test_wolfTPM2_SetIdentityAuth_RequiresPassword(void)
}
#endif /* WOLFTPM_MFG_IDENTITY && !SLB9672 && !SLB9673 */
/* wolfTPM2_EccKey_TpmToWolf must right-align coordinates: a spec-valid TPM
* coordinate with a stripped leading-zero byte (size < field size) would be
* left-aligned and scaled up, corrupting the imported point. */
static void test_wolfTPM2_EccKey_TpmToWolf_ShortCoord(void)
{
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \
!defined(WOLFTPM2_NO_WRAPPER) && !defined(NO_ECC256)
int rc, i, found = 0;
WC_RNG rng;
ecc_key genKey, impKey;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY tpmKey;
byte xRaw[32], yRaw[32];
byte xImp[32], yImp[32];
word32 xSz, ySz, xImpSz, yImpSz;
XMEMSET(&dev, 0, sizeof(dev));
AssertIntEQ(0, wc_InitRng(&rng));
/* Find a P-256 key whose x has a zero MSB so the stripped TPM form is
* shorter than the field size */
for (i = 0; i < 20000 && !found; i++) {
wc_ecc_init(&genKey);
rc = wc_ecc_make_key_ex(&rng, 32, &genKey, ECC_SECP256R1);
if (rc == 0) {
xSz = sizeof(xRaw);
ySz = sizeof(yRaw);
rc = wc_ecc_export_public_raw(&genKey, xRaw, &xSz, yRaw, &ySz);
}
if (rc == 0 && xSz == 32 && xRaw[0] == 0x00) {
found = 1;
}
wc_ecc_free(&genKey);
}
AssertIntEQ(1, found);
XMEMSET(&tpmKey, 0, sizeof(tpmKey));
tpmKey.pub.publicArea.type = TPM_ALG_ECC;
tpmKey.pub.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256;
tpmKey.pub.publicArea.unique.ecc.x.size = 31; /* leading zero stripped */
XMEMCPY(tpmKey.pub.publicArea.unique.ecc.x.buffer, xRaw + 1, 31);
tpmKey.pub.publicArea.unique.ecc.y.size = 32;
XMEMCPY(tpmKey.pub.publicArea.unique.ecc.y.buffer, yRaw, 32);
AssertIntEQ(0, wc_ecc_init(&impKey));
rc = wolfTPM2_EccKey_TpmToWolf(&dev, &tpmKey, &impKey);
AssertIntEQ(0, rc);
/* Imported point must equal the original full-width coordinates */
xImpSz = sizeof(xImp);
yImpSz = sizeof(yImp);
AssertIntEQ(0, wc_ecc_export_public_raw(&impKey, xImp, &xImpSz,
yImp, &yImpSz));
AssertIntEQ(0, XMEMCMP(xImp, xRaw, 32));
AssertIntEQ(0, XMEMCMP(yImp, yRaw, 32));
wc_ecc_free(&impKey);
wc_FreeRng(&rng);
printf("Test TPM Wrapper: %-40s Passed\n", "EccKey_TpmToWolf short coord:");
#endif
}
/* wolfTPM2_RsaKey_TpmToWolf must preserve the exponent for multi-byte
* non-palindromic values. The exponent bytes are big-endian on the wolfCrypt
* side, so a little-endian build would corrupt e.g. 0x010003. */
@ -6297,6 +6360,7 @@ int unit_tests(int argc, char *argv[])
!defined(WOLFTPM_SLB9672) && !defined(WOLFTPM_SLB9673)
test_wolfTPM2_SetIdentityAuth_RequiresPassword();
#endif
test_wolfTPM2_EccKey_TpmToWolf_ShortCoord();
test_wolfTPM2_RsaKey_TpmToWolf_Exponent();
test_wolfTPM2_EccZToBuffer();
test_wolfTPM2_LoadEccPublicKey_Ex();