mirror of https://github.com/wolfSSL/wolfTPM.git
Improve input digest size logic for TPM2_Sign and TPM2_Verify. Added test case with interop.
parent
32332fd2bb
commit
3e3038854c
|
@ -36,6 +36,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\tpm2.c" />
|
<ClCompile Include="..\..\src\tpm2.c" />
|
||||||
|
<ClCompile Include="..\..\src\tpm2_asn.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_cryptocb.c" />
|
<ClCompile Include="..\..\src\tpm2_cryptocb.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_packet.c" />
|
<ClCompile Include="..\..\src\tpm2_packet.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_param_enc.c" />
|
<ClCompile Include="..\..\src\tpm2_param_enc.c" />
|
||||||
|
|
|
@ -27,6 +27,21 @@
|
||||||
|
|
||||||
#ifndef WOLFTPM2_NO_ASN
|
#ifndef WOLFTPM2_NO_ASN
|
||||||
|
|
||||||
|
#if defined(HAVE_ECC) && (defined(WOLFTPM_CRYPTOCB) || \
|
||||||
|
(defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)))
|
||||||
|
/* Helper to trim leading zeros when not required */
|
||||||
|
byte* TPM2_ASN_TrimZeros(byte* in, word32* len)
|
||||||
|
{
|
||||||
|
word32 idx = 0;
|
||||||
|
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
|
||||||
|
idx++;
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
*len -= idx;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
|
int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
|
||||||
word32 maxIdx, int check)
|
word32 maxIdx, int check)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,24 +24,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <wolftpm/tpm2_wrap.h>
|
#include <wolftpm/tpm2_wrap.h>
|
||||||
|
#include <wolftpm/tpm2_asn.h>
|
||||||
|
|
||||||
#if !defined(WOLFTPM2_NO_WRAPPER)
|
#if !defined(WOLFTPM2_NO_WRAPPER)
|
||||||
|
|
||||||
#if defined(HAVE_ECC) && (defined(WOLFTPM_CRYPTOCB) || \
|
|
||||||
(defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)))
|
|
||||||
/* Helper to trim leading zeros when not required */
|
|
||||||
static byte* wolfTPM2_ASNTrimZeros(byte* in, word32* len)
|
|
||||||
{
|
|
||||||
word32 idx = 0;
|
|
||||||
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
|
|
||||||
idx++;
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
*len -= idx;
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFTPM_CRYPTOCB
|
#ifdef WOLFTPM_CRYPTOCB
|
||||||
|
|
||||||
/* Internal structure for tracking hash state */
|
/* Internal structure for tracking hash state */
|
||||||
|
@ -272,8 +258,8 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||||
rLen = sLen = rsLen / 2;
|
rLen = sLen = rsLen / 2;
|
||||||
r = &sigRS[0];
|
r = &sigRS[0];
|
||||||
s = &sigRS[rLen];
|
s = &sigRS[rLen];
|
||||||
r = wolfTPM2_ASNTrimZeros(r, &rLen);
|
r = TPM2_ASN_TrimZeros(r, &rLen);
|
||||||
s = wolfTPM2_ASNTrimZeros(s, &sLen);
|
s = TPM2_ASN_TrimZeros(s, &sLen);
|
||||||
|
|
||||||
/* Encode ECDSA Header */
|
/* Encode ECDSA Header */
|
||||||
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
|
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
|
||||||
|
@ -1134,8 +1120,8 @@ int wolfTPM2_PK_EccSign(WOLFSSL* ssl,
|
||||||
rLen = sLen = rsLen / 2;
|
rLen = sLen = rsLen / 2;
|
||||||
r = &sigRS[0];
|
r = &sigRS[0];
|
||||||
s = &sigRS[rLen];
|
s = &sigRS[rLen];
|
||||||
r = wolfTPM2_ASNTrimZeros(r, &rLen);
|
r = TPM2_ASN_TrimZeros(r, &rLen);
|
||||||
s = wolfTPM2_ASNTrimZeros(s, &sLen);
|
s = TPM2_ASN_TrimZeros(s, &sLen);
|
||||||
|
|
||||||
/* Encode ECDSA Header */
|
/* Encode ECDSA Header */
|
||||||
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz);
|
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz);
|
||||||
|
|
|
@ -3756,7 +3756,7 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
int sigOutSz = 0;
|
int sigOutSz = 0;
|
||||||
|
|
||||||
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
|
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
|
||||||
sigSz == NULL) {
|
sigSz == NULL) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3772,18 +3772,18 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
/* set session auth for key */
|
/* set session auth for key */
|
||||||
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
|
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
|
||||||
|
|
||||||
|
/* verify input cannot exceed buffer */
|
||||||
|
if (digestSz > (int)sizeof(signIn.digest.buffer))
|
||||||
|
digestSz = (int)sizeof(signIn.digest.buffer);
|
||||||
|
|
||||||
XMEMSET(&signIn, 0, sizeof(signIn));
|
XMEMSET(&signIn, 0, sizeof(signIn));
|
||||||
signIn.keyHandle = key->handle.hndl;
|
signIn.keyHandle = key->handle.hndl;
|
||||||
signIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
|
signIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
|
||||||
if (signIn.digest.size <= 0) {
|
if (signIn.digest.size <= 0) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
/* truncate if too large */
|
|
||||||
if (signIn.digest.size > curveSize) {
|
|
||||||
signIn.digest.size = curveSize;
|
|
||||||
}
|
|
||||||
/* if digest provided is smaller than key size then zero pad leading */
|
/* if digest provided is smaller than key size then zero pad leading */
|
||||||
if (signIn.digest.size > digestSz) {
|
if (digestSz < signIn.digest.size) {
|
||||||
XMEMCPY(&signIn.digest.buffer[signIn.digest.size - digestSz], digest,
|
XMEMCPY(&signIn.digest.buffer[signIn.digest.size - digestSz], digest,
|
||||||
digestSz);
|
digestSz);
|
||||||
}
|
}
|
||||||
|
@ -3932,8 +3932,20 @@ int wolfTPM2_VerifyHashTicket(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
|
|
||||||
XMEMSET(&verifySigIn, 0, sizeof(verifySigIn));
|
XMEMSET(&verifySigIn, 0, sizeof(verifySigIn));
|
||||||
verifySigIn.keyHandle = key->handle.hndl;
|
verifySigIn.keyHandle = key->handle.hndl;
|
||||||
verifySigIn.digest.size = digestSz;
|
|
||||||
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
|
|
||||||
|
verifySigIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
|
||||||
|
if (verifySigIn.digest.size <= 0) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
/* if digest provided is smaller than key size then zero pad leading */
|
||||||
|
if (digestSz < verifySigIn.digest.size) {
|
||||||
|
XMEMCPY(&verifySigIn.digest.buffer[verifySigIn.digest.size - digestSz],
|
||||||
|
digest, digestSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
|
||||||
|
}
|
||||||
verifySigIn.signature.sigAlg = sigAlg;
|
verifySigIn.signature.sigAlg = sigAlg;
|
||||||
verifySigIn.signature.signature.any.hashAlg = hashAlg;
|
verifySigIn.signature.signature.any.hashAlg = hashAlg;
|
||||||
if (key->pub.publicArea.type == TPM_ALG_ECC) {
|
if (key->pub.publicArea.type == TPM_ALG_ECC) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <wolftpm/tpm2.h>
|
#include <wolftpm/tpm2.h>
|
||||||
#include <wolftpm/tpm2_wrap.h>
|
#include <wolftpm/tpm2_wrap.h>
|
||||||
#include <wolftpm/tpm2_param_enc.h>
|
#include <wolftpm/tpm2_param_enc.h>
|
||||||
|
#include <wolftpm/tpm2_asn.h>
|
||||||
|
|
||||||
#include <hal/tpm_io.h>
|
#include <hal/tpm_io.h>
|
||||||
#include <examples/tpm_test.h>
|
#include <examples/tpm_test.h>
|
||||||
|
@ -396,6 +397,153 @@ static void test_wolfTPM2_CSR(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
|
||||||
|
static void test_wolfTPM2_EccSignVerifyDig(const byte* digest, int digestSz,
|
||||||
|
TPM_ECC_CURVE curve, TPMI_ALG_HASH hashAlg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int verifyRes = 0;
|
||||||
|
WOLFTPM2_DEV dev;
|
||||||
|
WOLFTPM2_KEY storageKey;
|
||||||
|
WOLFTPM2_KEY eccKey;
|
||||||
|
TPMT_PUBLIC publicTemplate;
|
||||||
|
byte sigRs[MAX_ECC_BYTES*2];
|
||||||
|
word32 sigRsSz = (word32)sizeof(sigRs);
|
||||||
|
byte sig[ECC_MAX_SIG_SIZE];
|
||||||
|
word32 sigSz;
|
||||||
|
byte *r, *s;
|
||||||
|
word32 rLen, sLen;
|
||||||
|
ecc_key wolfKey;
|
||||||
|
int curveSize = TPM2_GetCurveSize(curve);
|
||||||
|
|
||||||
|
/* Initialize TPM */
|
||||||
|
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* -- Use TPM key to sign and verify with wolfCrypt -- */
|
||||||
|
/* Create storage key */
|
||||||
|
rc = wolfTPM2_CreateSRK(&dev, &storageKey, TPM_ALG_ECC,
|
||||||
|
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Create ECC key for signing */
|
||||||
|
rc = wolfTPM2_GetKeyTemplate_ECC_ex(&publicTemplate, hashAlg,
|
||||||
|
(TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
|
||||||
|
TPMA_OBJECT_sign | TPMA_OBJECT_noDA),
|
||||||
|
curve, TPM_ALG_ECDSA, hashAlg);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
rc = wolfTPM2_CreateAndLoadKey(&dev, &eccKey, &storageKey.handle,
|
||||||
|
&publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Sign with TPM */
|
||||||
|
rc = wolfTPM2_SignHashScheme(&dev, &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);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Convert TPM key to wolfCrypt key for verification */
|
||||||
|
rc = wolfTPM2_EccKey_TpmToWolf(&dev, &eccKey, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Verify TPM signature with wolfCrypt */
|
||||||
|
rc = wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verifyRes, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
AssertIntEQ(verifyRes, 1); /* 1 indicates successful verification */
|
||||||
|
|
||||||
|
/* Cleanup first wolfCrypt key */
|
||||||
|
wc_ecc_free(&wolfKey);
|
||||||
|
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
|
||||||
|
|
||||||
|
|
||||||
|
/* -- Use wolfCrypt key to sign and verify with TPM -- */
|
||||||
|
/* Initialize new wolfCrypt ECC key */
|
||||||
|
rc = wc_ecc_init(&wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Generate new ECC key with wolfCrypt */
|
||||||
|
rc = wc_ecc_make_key(wolfTPM2_GetRng(&dev), curveSize, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Sign with wolfCrypt */
|
||||||
|
sigSz = (word32)sizeof(sig);
|
||||||
|
rc = wc_ecc_sign_hash(digest, digestSz, sig, &sigSz,
|
||||||
|
wolfTPM2_GetRng(&dev), &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Convert wolfCrypt key to TPM key for verification */
|
||||||
|
rc = wolfTPM2_EccKey_WolfToTpm(&dev, &wolfKey, &eccKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* combine R and S at key size (zero pad leading) */
|
||||||
|
XMEMCPY(&sigRs[curveSize-rLen], r, rLen);
|
||||||
|
XMEMSET(&sigRs[0], 0, curveSize-rLen);
|
||||||
|
XMEMCPY(&sigRs[curveSize + (curveSize-sLen)], s, sLen);
|
||||||
|
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);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
wc_ecc_free(&wolfKey);
|
||||||
|
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
|
||||||
|
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
|
||||||
|
wolfTPM2_Cleanup(&dev);
|
||||||
|
|
||||||
|
printf("Test TPM Wrapper:\tSign/Verify Interop (digestSz=%d, curve=%d, hashAlg=%d):\t%s\n",
|
||||||
|
digestSz, curve, hashAlg, rc == 0 ? "Passed" : "Failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 i;
|
||||||
|
byte digest[TPM_MAX_DIGEST_SIZE];
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
digest[i] = (byte)(0x11 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 20, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 32, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 48, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 64, TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
|
||||||
|
#if defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 20, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 32, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 48, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(digest, 64, TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \
|
||||||
!defined(NO_RSA)
|
!defined(NO_RSA)
|
||||||
static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */
|
static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */
|
||||||
|
@ -681,6 +829,9 @@ int unit_tests(int argc, char *argv[])
|
||||||
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
|
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
|
||||||
test_wolfTPM2_Cleanup();
|
test_wolfTPM2_Cleanup();
|
||||||
test_wolfTPM2_thread_local_storage();
|
test_wolfTPM2_thread_local_storage();
|
||||||
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC)
|
||||||
|
test_wolfTPM2_EccSignVerify();
|
||||||
|
#endif
|
||||||
#endif /* !WOLFTPM2_NO_WRAPPER */
|
#endif /* !WOLFTPM2_NO_WRAPPER */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -139,6 +139,10 @@ WOLFTPM_API int TPM2_ASN_DecodeRsaPubKey(uint8_t* input, int inputSz, TPM2B_PUBL
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_RsaUnpadPkcsv15(uint8_t** pSig, int* sigSz);
|
WOLFTPM_API int TPM2_ASN_RsaUnpadPkcsv15(uint8_t** pSig, int* sigSz);
|
||||||
|
|
||||||
|
|
||||||
|
WOLFTPM_LOCAL byte* TPM2_ASN_TrimZeros(byte* in, word32* len);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue