Skip to content

Commit 3e30388

Browse files
committed
Improve input digest size logic for TPM2_Sign and TPM2_Verify. Added test case with interop.
1 parent 32332fd commit 3e30388

6 files changed

Lines changed: 196 additions & 27 deletions

File tree

IDE/VisualStudio/wolftpm.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
</ItemGroup>
3737
<ItemGroup>
3838
<ClCompile Include="..\..\src\tpm2.c" />
39+
<ClCompile Include="..\..\src\tpm2_asn.c" />
3940
<ClCompile Include="..\..\src\tpm2_cryptocb.c" />
4041
<ClCompile Include="..\..\src\tpm2_packet.c" />
4142
<ClCompile Include="..\..\src\tpm2_param_enc.c" />

src/tpm2_asn.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@
2727

2828
#ifndef WOLFTPM2_NO_ASN
2929

30+
#if defined(HAVE_ECC) && (defined(WOLFTPM_CRYPTOCB) || \
31+
(defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)))
32+
/* Helper to trim leading zeros when not required */
33+
byte* TPM2_ASN_TrimZeros(byte* in, word32* len)
34+
{
35+
word32 idx = 0;
36+
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
37+
idx++;
38+
in++;
39+
}
40+
*len -= idx;
41+
return in;
42+
}
43+
#endif
44+
3045
int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
3146
word32 maxIdx, int check)
3247
{

src/tpm2_cryptocb.c

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,10 @@
2424
#endif
2525

2626
#include <wolftpm/tpm2_wrap.h>
27+
#include <wolftpm/tpm2_asn.h>
2728

2829
#if !defined(WOLFTPM2_NO_WRAPPER)
2930

30-
#if defined(HAVE_ECC) && (defined(WOLFTPM_CRYPTOCB) || \
31-
(defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)))
32-
/* Helper to trim leading zeros when not required */
33-
static byte* wolfTPM2_ASNTrimZeros(byte* in, word32* len)
34-
{
35-
word32 idx = 0;
36-
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
37-
idx++;
38-
in++;
39-
}
40-
*len -= idx;
41-
return in;
42-
}
43-
#endif
44-
4531
#ifdef WOLFTPM_CRYPTOCB
4632

4733
/* Internal structure for tracking hash state */
@@ -272,8 +258,8 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
272258
rLen = sLen = rsLen / 2;
273259
r = &sigRS[0];
274260
s = &sigRS[rLen];
275-
r = wolfTPM2_ASNTrimZeros(r, &rLen);
276-
s = wolfTPM2_ASNTrimZeros(s, &sLen);
261+
r = TPM2_ASN_TrimZeros(r, &rLen);
262+
s = TPM2_ASN_TrimZeros(s, &sLen);
277263

278264
/* Encode ECDSA Header */
279265
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
@@ -1134,8 +1120,8 @@ int wolfTPM2_PK_EccSign(WOLFSSL* ssl,
11341120
rLen = sLen = rsLen / 2;
11351121
r = &sigRS[0];
11361122
s = &sigRS[rLen];
1137-
r = wolfTPM2_ASNTrimZeros(r, &rLen);
1138-
s = wolfTPM2_ASNTrimZeros(s, &sLen);
1123+
r = TPM2_ASN_TrimZeros(r, &rLen);
1124+
s = TPM2_ASN_TrimZeros(s, &sLen);
11391125

11401126
/* Encode ECDSA Header */
11411127
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz);

src/tpm2_wrap.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,7 +3756,7 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
37563756
int sigOutSz = 0;
37573757

37583758
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
3759-
sigSz == NULL) {
3759+
sigSz == NULL) {
37603760
return BAD_FUNC_ARG;
37613761
}
37623762

@@ -3772,18 +3772,18 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
37723772
/* set session auth for key */
37733773
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
37743774

3775+
/* verify input cannot exceed buffer */
3776+
if (digestSz > (int)sizeof(signIn.digest.buffer))
3777+
digestSz = (int)sizeof(signIn.digest.buffer);
3778+
37753779
XMEMSET(&signIn, 0, sizeof(signIn));
37763780
signIn.keyHandle = key->handle.hndl;
37773781
signIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
37783782
if (signIn.digest.size <= 0) {
37793783
return BAD_FUNC_ARG;
37803784
}
3781-
/* truncate if too large */
3782-
if (signIn.digest.size > curveSize) {
3783-
signIn.digest.size = curveSize;
3784-
}
37853785
/* if digest provided is smaller than key size then zero pad leading */
3786-
if (signIn.digest.size > digestSz) {
3786+
if (digestSz < signIn.digest.size) {
37873787
XMEMCPY(&signIn.digest.buffer[signIn.digest.size - digestSz], digest,
37883788
digestSz);
37893789
}
@@ -3932,8 +3932,20 @@ int wolfTPM2_VerifyHashTicket(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
39323932

39333933
XMEMSET(&verifySigIn, 0, sizeof(verifySigIn));
39343934
verifySigIn.keyHandle = key->handle.hndl;
3935-
verifySigIn.digest.size = digestSz;
3936-
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
3935+
3936+
3937+
verifySigIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
3938+
if (verifySigIn.digest.size <= 0) {
3939+
return BAD_FUNC_ARG;
3940+
}
3941+
/* if digest provided is smaller than key size then zero pad leading */
3942+
if (digestSz < verifySigIn.digest.size) {
3943+
XMEMCPY(&verifySigIn.digest.buffer[verifySigIn.digest.size - digestSz],
3944+
digest, digestSz);
3945+
}
3946+
else {
3947+
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
3948+
}
39373949
verifySigIn.signature.sigAlg = sigAlg;
39383950
verifySigIn.signature.signature.any.hashAlg = hashAlg;
39393951
if (key->pub.publicArea.type == TPM_ALG_ECC) {

tests/unit_tests.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <wolftpm/tpm2.h>
2929
#include <wolftpm/tpm2_wrap.h>
3030
#include <wolftpm/tpm2_param_enc.h>
31+
#include <wolftpm/tpm2_asn.h>
3132

3233
#include <hal/tpm_io.h>
3334
#include <examples/tpm_test.h>
@@ -396,6 +397,153 @@ static void test_wolfTPM2_CSR(void)
396397
#endif
397398
}
398399

400+
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
401+
static void test_wolfTPM2_EccSignVerifyDig(const byte* digest, int digestSz,
402+
TPM_ECC_CURVE curve, TPMI_ALG_HASH hashAlg)
403+
{
404+
int rc;
405+
int verifyRes = 0;
406+
WOLFTPM2_DEV dev;
407+
WOLFTPM2_KEY storageKey;
408+
WOLFTPM2_KEY eccKey;
409+
TPMT_PUBLIC publicTemplate;
410+
byte sigRs[MAX_ECC_BYTES*2];
411+
word32 sigRsSz = (word32)sizeof(sigRs);
412+
byte sig[ECC_MAX_SIG_SIZE];
413+
word32 sigSz;
414+
byte *r, *s;
415+
word32 rLen, sLen;
416+
ecc_key wolfKey;
417+
int curveSize = TPM2_GetCurveSize(curve);
418+
419+
/* Initialize TPM */
420+
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
421+
AssertIntEQ(rc, 0);
422+
423+
/* -- Use TPM key to sign and verify with wolfCrypt -- */
424+
/* Create storage key */
425+
rc = wolfTPM2_CreateSRK(&dev, &storageKey, TPM_ALG_ECC,
426+
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
427+
AssertIntEQ(rc, 0);
428+
429+
/* Create ECC key for signing */
430+
rc = wolfTPM2_GetKeyTemplate_ECC_ex(&publicTemplate, hashAlg,
431+
(TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
432+
TPMA_OBJECT_sign | TPMA_OBJECT_noDA),
433+
curve, TPM_ALG_ECDSA, hashAlg);
434+
AssertIntEQ(rc, 0);
435+
rc = wolfTPM2_CreateAndLoadKey(&dev, &eccKey, &storageKey.handle,
436+
&publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1);
437+
AssertIntEQ(rc, 0);
438+
439+
/* Sign with TPM */
440+
rc = wolfTPM2_SignHashScheme(&dev, &eccKey, digest, digestSz,
441+
sigRs, (int*)&sigRsSz, TPM_ALG_ECDSA, hashAlg);
442+
AssertIntEQ(rc, 0);
443+
444+
/* Make sure leading zero's not required are trimmed */
445+
rLen = sLen = sigRsSz / 2;
446+
r = &sigRs[0];
447+
s = &sigRs[rLen];
448+
r = TPM2_ASN_TrimZeros(r, &rLen);
449+
s = TPM2_ASN_TrimZeros(s, &sLen);
450+
451+
/* Encode ECDSA Header */
452+
sigSz = (word32)sizeof(sig);
453+
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, sig, &sigSz);
454+
AssertIntEQ(rc, 0);
455+
456+
/* Initialize wolfCrypt ECC key */
457+
rc = wc_ecc_init(&wolfKey);
458+
AssertIntEQ(rc, 0);
459+
460+
/* Convert TPM key to wolfCrypt key for verification */
461+
rc = wolfTPM2_EccKey_TpmToWolf(&dev, &eccKey, &wolfKey);
462+
AssertIntEQ(rc, 0);
463+
464+
/* Verify TPM signature with wolfCrypt */
465+
rc = wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verifyRes, &wolfKey);
466+
AssertIntEQ(rc, 0);
467+
AssertIntEQ(verifyRes, 1); /* 1 indicates successful verification */
468+
469+
/* Cleanup first wolfCrypt key */
470+
wc_ecc_free(&wolfKey);
471+
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
472+
473+
474+
/* -- Use wolfCrypt key to sign and verify with TPM -- */
475+
/* Initialize new wolfCrypt ECC key */
476+
rc = wc_ecc_init(&wolfKey);
477+
AssertIntEQ(rc, 0);
478+
479+
/* Generate new ECC key with wolfCrypt */
480+
rc = wc_ecc_make_key(wolfTPM2_GetRng(&dev), curveSize, &wolfKey);
481+
AssertIntEQ(rc, 0);
482+
483+
/* Sign with wolfCrypt */
484+
sigSz = (word32)sizeof(sig);
485+
rc = wc_ecc_sign_hash(digest, digestSz, sig, &sigSz,
486+
wolfTPM2_GetRng(&dev), &wolfKey);
487+
AssertIntEQ(rc, 0);
488+
489+
/* Decode ECDSA Header */
490+
r = sigRs;
491+
s = &sigRs[MAX_ECC_BYTES];
492+
rLen = sLen = MAX_ECC_BYTES;
493+
rc = wc_ecc_sig_to_rs(sig,
494+
sigSz, r, &rLen, s, &sLen);
495+
AssertIntEQ(rc, 0);
496+
497+
/* Convert wolfCrypt key to TPM key for verification */
498+
rc = wolfTPM2_EccKey_WolfToTpm(&dev, &wolfKey, &eccKey);
499+
AssertIntEQ(rc, 0);
500+
501+
/* combine R and S at key size (zero pad leading) */
502+
XMEMCPY(&sigRs[curveSize-rLen], r, rLen);
503+
XMEMSET(&sigRs[0], 0, curveSize-rLen);
504+
XMEMCPY(&sigRs[curveSize + (curveSize-sLen)], s, sLen);
505+
XMEMSET(&sigRs[curveSize], 0, curveSize-sLen);
506+
507+
/* Verify wolfCrypt signature with TPM */
508+
rc = wolfTPM2_VerifyHashScheme(&dev, &eccKey, sigRs, curveSize*2,
509+
digest, digestSz, TPM_ALG_ECDSA, hashAlg);
510+
AssertIntEQ(rc, 0);
511+
512+
/* Cleanup */
513+
wc_ecc_free(&wolfKey);
514+
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
515+
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
516+
wolfTPM2_Cleanup(&dev);
517+
518+
printf("Test TPM Wrapper:\tSign/Verify Interop (digestSz=%d, curve=%d, hashAlg=%d):\t%s\n",
519+
digestSz, curve, hashAlg, rc == 0 ? "Passed" : "Failed");
520+
}
521+
522+
/* Test with smaller, same and larger digest sizes using different ECC curves.
523+
* Interop sign and verify with wolfCrypt and TPM */
524+
static void test_wolfTPM2_EccSignVerify(void)
525+
{
526+
int i;
527+
byte digest[TPM_MAX_DIGEST_SIZE];
528+
529+
for (i = 0; i < 64; i++) {
530+
digest[i] = (byte)(0x11 + i);
531+
}
532+
533+
test_wolfTPM2_EccSignVerifyDig(digest, 20, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
534+
test_wolfTPM2_EccSignVerifyDig(digest, 32, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
535+
test_wolfTPM2_EccSignVerifyDig(digest, 48, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
536+
test_wolfTPM2_EccSignVerifyDig(digest, 64, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
537+
538+
#if defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
539+
test_wolfTPM2_EccSignVerifyDig(digest, 20, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
540+
test_wolfTPM2_EccSignVerifyDig(digest, 32, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
541+
test_wolfTPM2_EccSignVerifyDig(digest, 48, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
542+
test_wolfTPM2_EccSignVerifyDig(digest, 64, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
543+
#endif
544+
}
545+
#endif
546+
399547
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \
400548
!defined(NO_RSA)
401549
static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */
@@ -681,6 +829,9 @@ int unit_tests(int argc, char *argv[])
681829
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
682830
test_wolfTPM2_Cleanup();
683831
test_wolfTPM2_thread_local_storage();
832+
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
833+
test_wolfTPM2_EccSignVerify();
834+
#endif
684835
#endif /* !WOLFTPM2_NO_WRAPPER */
685836

686837
return 0;

wolftpm/tpm2_asn.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ WOLFTPM_API int TPM2_ASN_DecodeRsaPubKey(uint8_t* input, int inputSz, TPM2B_PUBL
139139
*/
140140
WOLFTPM_API int TPM2_ASN_RsaUnpadPkcsv15(uint8_t** pSig, int* sigSz);
141141

142+
143+
WOLFTPM_LOCAL byte* TPM2_ASN_TrimZeros(byte* in, word32* len);
144+
145+
142146
#ifdef __cplusplus
143147
} /* extern "C" */
144148
#endif

0 commit comments

Comments
 (0)