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
6 changes: 6 additions & 0 deletions src/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -6111,6 +6111,12 @@ const char* TPM2_GetAlgName(TPM_ALG_ID alg)
return "SHA384";
case TPM_ALG_SHA512:
return "SHA512";
case TPM_ALG_SHA3_256:
return "SHA3_256";
case TPM_ALG_SHA3_384:
return "SHA3_384";
case TPM_ALG_SHA3_512:
return "SHA3_512";
case TPM_ALG_NULL:
return "NULL";
case TPM_ALG_SM3_256:
Expand Down
6 changes: 2 additions & 4 deletions src/tpm2_cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,6 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
rLen = sLen = rsLen / 2;
r = &sigRS[0];
s = &sigRS[rLen];
r = TPM2_ASN_TrimZeros(r, &rLen);
s = TPM2_ASN_TrimZeros(s, &sLen);

/* Encode ECDSA Header */
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
Expand All @@ -355,9 +353,9 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
if (rc == 0) {
/* combine R and S at key size (zero pad leading) */
word32 keySz = wc_ecc_size(info->pk.eccverify.key);
XMEMCPY(&sigRS[keySz-rLen], r, rLen);
XMEMMOVE(&sigRS[keySz-rLen], r, rLen);
XMEMSET(&sigRS[0], 0, keySz-rLen);
XMEMCPY(&sigRS[keySz + (keySz-sLen)], s, sLen);
XMEMMOVE(&sigRS[keySz + (keySz-sLen)], s, sLen);
XMEMSET(&sigRS[keySz], 0, keySz-sLen);
rc = wolfTPM2_VerifyHash(tlsCtx->dev, &eccPub,
sigRS, keySz*2,
Expand Down
33 changes: 19 additions & 14 deletions src/tpm2_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -4080,32 +4080,37 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
}

if (key->pub.publicArea.type == TPM_ALG_ECC) {
TPMS_SIGNATURE_ECDSA* ecdsa = &signOut.signature.signature.ecdsa;

/* Assemble R and S into signature (R then S) */
sigOutSz = signOut.signature.signature.ecdsa.signatureR.size +
signOut.signature.signature.ecdsa.signatureS.size;
if (sigOutSz > *sigSz) {
sigOutSz = curveSize * 2;
if (sigOutSz > *sigSz ||
curveSize > ecdsa->signatureR.size ||
curveSize > ecdsa->signatureS.size) {
#ifdef DEBUG_WOLFTPM
printf("TPM2_Sign: ECC result truncated %d -> %d\n",
printf("TPM2_Sign: ECC result buffer too small %d -> %d\n",
sigOutSz, *sigSz);
#endif
sigOutSz = *sigSz;
return BUFFER_E;
}
XMEMCPY(sig,
signOut.signature.signature.ecdsa.signatureR.buffer,
signOut.signature.signature.ecdsa.signatureR.size);
XMEMCPY(sig + signOut.signature.signature.ecdsa.signatureR.size,
signOut.signature.signature.ecdsa.signatureS.buffer,
signOut.signature.signature.ecdsa.signatureS.size);
XMEMCPY(sig, ecdsa->signatureR.buffer,
ecdsa->signatureR.size);
XMEMSET(sig + ecdsa->signatureR.size, 0,
curveSize - ecdsa->signatureR.size);
XMEMCPY(sig + curveSize, ecdsa->signatureS.buffer,
ecdsa->signatureS.size);
XMEMSET(sig + curveSize + ecdsa->signatureS.size, 0,
curveSize - ecdsa->signatureS.size);
}
else if (key->pub.publicArea.type == TPM_ALG_RSA) {
/* RSA signature size and buffer (with padding depending on scheme) */
sigOutSz = signOut.signature.signature.rsassa.sig.size;
if (sigOutSz > *sigSz) {
#ifdef DEBUG_WOLFTPM
printf("TPM2_Sign: RSA result truncated %d -> %d\n",
printf("TPM2_Sign: RSA result buffer too small %d -> %d\n",
sigOutSz, *sigSz);
#endif
sigOutSz = *sigSz;
return BUFFER_E;
}
XMEMCPY(sig, signOut.signature.signature.rsassa.sig.buffer, sigOutSz);
}
Expand Down Expand Up @@ -7368,7 +7373,7 @@ static int CSR_MakeAndSign(WOLFTPM2_DEV* dev, WOLFTPM2_CSR* csr, CSRKey* key,
}
#else
#ifdef DEBUG_WOLFTPM
printf("CSR_MakeAndSign PEM not supported\n")
printf("CSR_MakeAndSign PEM not supported\n");
#endif
rc = NOT_COMPILED_IN;
#endif
Expand Down
136 changes: 95 additions & 41 deletions tests/unit_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,16 @@ static void test_wolfTPM2_CSR(void)

#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
!defined(WOLFTPM2_NO_ASN)
#define FLAGS_USE_WOLFCRYPT (1 << 0)
#define FLAGS_USE_CRYPTO_CB (1 << 1)
#define FLAGS_USE_PK_CB (1 << 2) /* requires TLS layer to test */
static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
WOLFTPM2_KEY* storageKey, const byte* digest, int digestSz,
TPM_ECC_CURVE curve, TPMI_ALG_HASH hashAlg)
TPM_ECC_CURVE curve, TPMI_ALG_HASH hashAlg, int flags)
{
int rc;
int verifyRes = 0;
WOLFTPM2_KEY eccKey;
WOLFTPM2_KEYBLOB eccKey;
TPMT_PUBLIC publicTemplate;
byte sigRs[MAX_ECC_BYTES*2];
word32 sigRsSz = (word32)sizeof(sigRs);
Expand All @@ -425,6 +428,21 @@ static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
word32 rLen, sLen;
ecc_key wolfKey;
int curveSize = TPM2_GetCurveSize(curve);
#ifdef WOLF_CRYPTO_CB
int tpmDevId = INVALID_DEVID;
TpmCryptoDevCtx tpmCtx;

XMEMSET(&tpmCtx, 0, sizeof(tpmCtx));
tpmCtx.dev = dev;
tpmCtx.ecdsaKey = &eccKey;
tpmCtx.storageKey = storageKey;

if (flags & FLAGS_USE_CRYPTO_CB) {
rc = wolfTPM2_SetCryptoDevCb(dev, wolfTPM2_CryptoDevCb, &tpmCtx,
&tpmDevId);
AssertIntEQ(rc, 0);
}
#endif

/* -- Use TPM key to sign and verify with wolfCrypt -- */
/* Create ECC key for signing */
Expand All @@ -433,37 +451,45 @@ static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
TPMA_OBJECT_sign | TPMA_OBJECT_noDA),
curve, TPM_ALG_ECDSA, hashAlg);
AssertIntEQ(rc, 0);
rc = wolfTPM2_CreateAndLoadKey(dev, &eccKey, &storageKey->handle,

/* Use create key and load key directly instead to make
* sure the private portion is populated */
rc = wolfTPM2_CreateKey(dev, &eccKey, &storageKey->handle,
&publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1);
if (rc == TPM_RC_SUCCESS) {
rc = wolfTPM2_LoadKey(dev, &eccKey, &storageKey->handle);
}
if ((rc & TPM_RC_HASH) == TPM_RC_HASH) {
printf("Hash type not supported... Skipping\n");
return;
}
if ((rc & TPM_RC_CURVE) == TPM_RC_CURVE) {
printf("Curve not supported... Skipping\n");
return;
}
AssertIntEQ(rc, 0);

/* Sign with TPM */
rc = wolfTPM2_SignHashScheme(dev, &eccKey, digest, digestSz,
rc = wolfTPM2_SignHashScheme(dev, (WOLFTPM2_KEY*)&eccKey, digest, digestSz,
sigRs, (int*)&sigRsSz, TPM_ALG_ECDSA, hashAlg);
AssertIntEQ(rc, 0);

/* Make sure leading zero's not required are trimmed */
rLen = sLen = sigRsSz / 2;
r = &sigRs[0];
s = &sigRs[rLen];
r = TPM2_ASN_TrimZeros(r, &rLen);
s = TPM2_ASN_TrimZeros(s, &sLen);

/* Encode ECDSA Header */
sigSz = (word32)sizeof(sig);
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, sig, &sigSz);
AssertIntEQ(rc, 0);

/* Initialize wolfCrypt ECC key */
rc = wc_ecc_init(&wolfKey);
rc = wc_ecc_init_ex(&wolfKey, NULL, tpmDevId);
AssertIntEQ(rc, 0);

/* Convert TPM key to wolfCrypt key for verification */
rc = wolfTPM2_EccKey_TpmToWolf(dev, &eccKey, &wolfKey);
rc = wolfTPM2_EccKey_TpmToWolf(dev, (WOLFTPM2_KEY*)&eccKey, &wolfKey);
AssertIntEQ(rc, 0);

/* Verify TPM signature with wolfCrypt */
Expand All @@ -474,11 +500,13 @@ static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
/* Cleanup first wolfCrypt key */
wc_ecc_free(&wolfKey);
wolfTPM2_UnloadHandle(dev, &eccKey.handle);

#ifdef WOLF_CRYPTO_CB
tpmCtx.ecdsaKey = NULL; /* create new one */
#endif

/* -- Use wolfCrypt key to sign and verify with TPM -- */
/* Initialize new wolfCrypt ECC key */
rc = wc_ecc_init(&wolfKey);
rc = wc_ecc_init_ex(&wolfKey, NULL, tpmDevId);
AssertIntEQ(rc, 0);

/* Generate new ECC key with wolfCrypt */
Expand All @@ -490,17 +518,17 @@ static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
rc = wc_ecc_sign_hash(digest, digestSz, sig, &sigSz, wolfTPM2_GetRng(dev),
&wolfKey);
AssertIntEQ(rc, 0);
wolfTPM2_UnloadHandle(dev, &eccKey.handle);

/* Decode ECDSA Header */
r = sigRs;
s = &sigRs[MAX_ECC_BYTES];
rLen = sLen = MAX_ECC_BYTES;
rc = wc_ecc_sig_to_rs(sig,
sigSz, r, &rLen, s, &sLen);
rc = wc_ecc_sig_to_rs(sig, sigSz, r, &rLen, s, &sLen);
AssertIntEQ(rc, 0);

/* Convert wolfCrypt key to TPM key for verification */
rc = wolfTPM2_EccKey_WolfToTpm(dev, &wolfKey, &eccKey);
rc = wolfTPM2_EccKey_WolfToTpm(dev, &wolfKey, (WOLFTPM2_KEY*)&eccKey);
AssertIntEQ(rc, 0);

/* combine R and S at key size (zero pad leading) */
Expand All @@ -510,27 +538,73 @@ static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
XMEMSET(&sigRs[curveSize], 0, curveSize-sLen);

/* Verify wolfCrypt signature with TPM */
rc = wolfTPM2_VerifyHashScheme(dev, &eccKey, sigRs, curveSize*2,
digest, digestSz, TPM_ALG_ECDSA, hashAlg);
rc = wolfTPM2_VerifyHashScheme(dev, (WOLFTPM2_KEY*)&eccKey, sigRs,
curveSize*2, digest, digestSz, TPM_ALG_ECDSA, hashAlg);
AssertIntEQ(rc, 0);

/* Cleanup */
wc_ecc_free(&wolfKey);
wolfTPM2_UnloadHandle(dev, &eccKey.handle);

printf("Test TPM Wrapper:\t"
"Sign/Verify (DigSz=%d, CurveSz=%d, Hash=%s):"
"Sign/Verify (DigSz=%d, CurveSz=%d, Hash=%s, Flags=%s):"
"\t%s\n",
digestSz, TPM2_GetCurveSize(curve), TPM2_GetAlgName(hashAlg),
(flags & FLAGS_USE_CRYPTO_CB) ? "Crypto CB" : "",
rc == 0 ? "Passed" : "Failed");

if (flags & FLAGS_USE_CRYPTO_CB) {
wolfTPM2_ClearCryptoDevCb(dev, tpmDevId);
}
}

static void test_wolfTPM2_EccSignVerify_All(WOLFTPM2_DEV* dev,
WOLFTPM2_KEY* storageKey, int flags)
{
int i;
byte digest[TPM_MAX_DIGEST_SIZE];

for (i = 0; i < (int)sizeof(digest); i++) {
digest[i] = (byte)i;
}

test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 20,
TPM_ECC_NIST_P256, TPM_ALG_SHA256, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 32,
TPM_ECC_NIST_P256, TPM_ALG_SHA256, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 48,
TPM_ECC_NIST_P256, TPM_ALG_SHA256, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 64,
TPM_ECC_NIST_P256, TPM_ALG_SHA256, flags);

#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 20,
TPM_ECC_NIST_P384, TPM_ALG_SHA384, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 32,
TPM_ECC_NIST_P384, TPM_ALG_SHA384, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 48,
TPM_ECC_NIST_P384, TPM_ALG_SHA384, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 64,
TPM_ECC_NIST_P384, TPM_ALG_SHA384, flags);
#endif

#if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 20,
TPM_ECC_NIST_P521, TPM_ALG_SHA512, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 32,
TPM_ECC_NIST_P521, TPM_ALG_SHA512, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 48,
TPM_ECC_NIST_P521, TPM_ALG_SHA512, flags);
test_wolfTPM2_EccSignVerifyDig(dev, storageKey, digest, 64,
TPM_ECC_NIST_P521, TPM_ALG_SHA512, flags);
#endif
}

/* Test with smaller, same and larger digest sizes using different ECC curves.
* Interop sign and verify with wolfCrypt and TPM */
static void test_wolfTPM2_EccSignVerify(void)
{
int rc, i;
byte digest[TPM_MAX_DIGEST_SIZE];
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storageKey;

Expand All @@ -543,29 +617,9 @@ static void test_wolfTPM2_EccSignVerify(void)
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
AssertIntEQ(rc, 0);


for (i = 0; i < (int)sizeof(digest); i++) {
digest[i] = (byte)i;
}

test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 20,
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 32,
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 48,
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 64,
TPM_ECC_NIST_P256, TPM_ALG_SHA256);

#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 20,
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 32,
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 48,
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 64,
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
test_wolfTPM2_EccSignVerify_All(&dev, &storageKey, 0);
#ifdef WOLF_CRYPTO_CB
test_wolfTPM2_EccSignVerify_All(&dev, &storageKey, FLAGS_USE_CRYPTO_CB);
#endif

wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
Expand Down