Added PKCS7 ECC support to example. Added wrapper function to export TPM public key as DER/ASN.1 or PEM. Fix for crypto callback ECC sign to handle getting keySz for unknown cases (like PKCS7 without privateKey set).

pull/322/head
David Garske 2024-01-17 14:08:14 -08:00
parent e54734a3ab
commit 0aa01f4f5a
11 changed files with 375 additions and 225 deletions

View File

@ -110,10 +110,14 @@ The script creates the following X.509 files (also in .pem format):
Example signs and verifies data with PKCS #7 using a TPM based key.
* Must first run:
1. `./examples/csr/csr`
2. `./certs/certreq.sh`
3. `./examples/pkcs7/pkcs7`
```sh
./examples/keygen/keygen rsa_test_blob.raw -rsa -t
./examples/keygen/keygen ecc_test_blob.raw -ecc -t
./examples/csr/csr
./certs/certreq.sh
./examples/pkcs7/pkcs7
./examples/pkcs7/pkcs7 -ecc
```
The result is displayed to stdout on the console.

View File

@ -186,17 +186,18 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[])
rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx,
&tpmDevId);
if (rc == 0) {
/* See if primary storage key already exists */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA);
}
#ifndef NO_RSA
if (rc == 0) {
tpmCtx.rsaKey = &key; /* Setup the wolf crypto device callback */
rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate,
/* open the RSA SRK */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA);
if (rc == 0) {
rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA);
}
if (rc == 0) {
rc = getRSAkey(&dev, &storageKey, &key, NULL, tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1, &publicTemplate);
@ -207,6 +208,7 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[])
makeSelfSignedCert, tpmDevId, CTC_SHA256wRSA);
}
wolfTPM2_UnloadHandle(&dev, &key.handle);
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
}
#endif /* !NO_RSA */
@ -214,18 +216,21 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[])
if (rc == 0) {
int sigType = CTC_SHA256wECDSA;
TPM_ECC_CURVE curve = TPM_ECC_NIST_P256;
tpmCtx.eccKey = &key;
#if defined(NO_ECC256) && defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
/* make sure we use a curve that is enabled */
sigType = CTC_SHA384wECDSA;
curve = TPM_ECC_NIST_P384;
#endif
tpmCtx.eccKey = &key;
rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
/* open the ECC SRK */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_ECC);
if (rc == 0) {
rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
curve, TPM_ALG_ECDSA);
}
if (rc == 0) {
rc = getECCkey(&dev, &storageKey, &key, NULL, tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1, &publicTemplate);
@ -236,6 +241,7 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[])
makeSelfSignedCert, tpmDevId, sigType);
}
wolfTPM2_UnloadHandle(&dev, &key.handle);
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
}
#endif /* HAVE_ECC */
@ -243,7 +249,6 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[])
printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc));
}
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
wolfTPM2_Cleanup(&dev);
return rc;

View File

@ -232,14 +232,18 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
}
if (endorseKey) {
/* endorsement is always RSA */
rc = wolfTPM2_CreateEK(&dev, &endorse, TPM_ALG_RSA);
endorse.handle.policyAuth = 1; /* EK requires Policy auth, not Password */
pubFilename = ekPubFile;
primary = &endorse;
}
else {
/* get SRK */
rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA);
/* SRK: Use RSA or ECC SRK only. Prefer ECC */
TPMI_ALG_PUBLIC srkAlg = TPM_ALG_ECC;
if (alg == TPM_ALG_RSA)
srkAlg = TPM_ALG_RSA;
rc = getPrimaryStoragekey(&dev, &storage, srkAlg);
pubFilename = srkPubFile;
primary = &storage;
}
@ -403,7 +407,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
pemFilename = (endorseKey) ? pemFileEk : pemFileSrk;
pemSz = (word32)sizeof(pem);
rc = wolfTPM2_RsaKey_TpmToPemPub(&dev, primary, pem, &pemSz);
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, primary,
ENCODING_TYPE_PEM, pem, &pemSz);
if (rc == 0) {
rc = writeBin(pemFilename, pem, pemSz);
}
@ -411,8 +416,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
pemFilename = (bAIK) ? pemFileAk : pemFileKey;
pemSz = (word32)sizeof(pem);
rc = wolfTPM2_RsaKey_TpmToPemPub(&dev, (WOLFTPM2_KEY*)&newKeyBlob,
pem, &pemSz);
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, (WOLFTPM2_KEY*)&newKeyBlob,
ENCODING_TYPE_PEM, pem, &pemSz);
if (rc == 0) {
rc = writeBin(pemFilename, pem, pemSz);
}

View File

@ -116,14 +116,29 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[])
goto exit;
}
/* Load encrypted key from the disk */
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
rc = readKeyBlob(inputFile, &newKey);
if (rc != 0) goto exit;
#else
/* TODO: Option to load hex blob */
printf("Loading blob from disk not supported. Enable wolfcrypt support.\n");
goto exit;
#endif
if (endorseKey) {
/* endorsement is always RSA */
rc = wolfTPM2_CreateEK(&dev, &endorse, TPM_ALG_RSA);
if (rc != 0) goto exit;
endorse.handle.policyAuth = 1;
primary = &endorse;
}
else { /* SRK */
rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA);
else {
/* SRK: Use RSA or ECC SRK only. Prefer ECC */
TPMI_ALG_PUBLIC srkAlg = TPM_ALG_ECC;
if (newKey.pub.publicArea.type == TPM_ALG_RSA)
srkAlg = TPM_ALG_RSA;
rc = getPrimaryStoragekey(&dev, &storage, srkAlg);
if (rc != 0) goto exit;
primary = &storage;
}
@ -153,15 +168,6 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[])
if (rc != 0) goto exit;
}
/* Load encrypted key from the disk */
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
rc = readKeyBlob(inputFile, &newKey);
if (rc != 0) goto exit;
#else
/* TODO: Option to load hex blob */
printf("Loading blob from disk not supported. Enable wolfcrypt support.\n");
goto exit;
#endif
if (newKey.priv.size == 0) {
rc = wolfTPM2_LoadPublicKey(&dev, (WOLFTPM2_KEY*)&newKey, &newKey.pub);

View File

@ -89,14 +89,14 @@ static int GetMyData(byte* buffer, word32 bufSz, word32 offset)
/* The wc_PKCS7_EncodeSignedData_ex and wc_PKCS7_VerifySignedData_ex functions
were added in this PR https://github.com/wolfSSL/wolfssl/pull/1780. */
static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* der)
static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* derCert,
WOLFTPM2_BUFFER* derPubKey, int alg, enum wc_HashType hashType, const char* outFile)
{
int rc;
PKCS7 pkcs7;
wc_HashAlg hash;
enum wc_HashType hashType = WC_HASH_TYPE_SHA256;
byte hashBuf[TPM_SHA256_DIGEST_SIZE];
word32 hashSz = wc_HashGetDigestSize(hashType);
byte hashBuf[TPM_MAX_DIGEST_SIZE];
word32 hashSz;
byte outputHead[MAX_PKCS7_SIZE], outputFoot[MAX_PKCS7_SIZE];
int outputHeadSz, outputFootSz;
byte dataChunk[MY_DATA_CHUNKS];
@ -107,6 +107,11 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER*
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
hashSz = wc_HashGetDigestSize(hashType);
if (hashSz <= 0) {
return hashSz;
}
/* calculate hash for content */
rc = wc_HashInit(&hash, hashType);
if (rc == 0) {
@ -131,14 +136,18 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER*
/* Generate and verify PKCS#7 files containing data using TPM key */
rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId);
if (rc != 0) goto exit;
rc = wc_PKCS7_InitWithCert(&pkcs7, der->buffer, der->size);
rc = wc_PKCS7_InitWithCert(&pkcs7, derCert->buffer, derCert->size);
if (rc != 0) goto exit;
pkcs7.content = NULL; /* not used */
pkcs7.contentSz = dataChunkSz;
pkcs7.encryptOID = RSAk;
pkcs7.hashOID = SHA256h;
pkcs7.encryptOID = (alg == TPM_ALG_RSA) ? RSAk : ECDSAk;
pkcs7.hashOID = wc_HashGetOID(hashType);
pkcs7.rng = wolfTPM2_GetRng(dev);
/* pass public key instead of private here. The PKCS7 will try a public
* key decode if using crypto callbacks */
pkcs7.privateKey = derPubKey->buffer;
pkcs7.privateKeySz = derPubKey->size;
outputHeadSz = (int)sizeof(outputHead);
outputFootSz = (int)sizeof(outputFoot);
@ -157,7 +166,7 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER*
TPM2_PrintBin(outputFoot, outputFootSz);
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
pemFile = XFOPEN("./examples/pkcs7/pkcs7tpmsignedex.p7s", "wb");
pemFile = XFOPEN(outFile, "wb");
if (pemFile != XBADFILE) {
/* Header */
@ -227,7 +236,8 @@ exit:
}
#endif /* ENABLE_PKCS7EX_EXAMPLE */
static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* der)
static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* derCert,
WOLFTPM2_BUFFER* derPubKey, int alg, enum wc_HashType hashType, const char* outFile)
{
int rc;
PKCS7 pkcs7;
@ -243,14 +253,18 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* de
/* Generate and verify PKCS#7 files containing data using TPM key */
rc = wc_PKCS7_Init(&pkcs7, NULL, tpmDevId);
if (rc != 0) goto exit;
rc = wc_PKCS7_InitWithCert(&pkcs7, der->buffer, der->size);
rc = wc_PKCS7_InitWithCert(&pkcs7, derCert->buffer, derCert->size);
if (rc != 0) goto exit;
pkcs7.content = data;
pkcs7.contentSz = (word32)sizeof(data);
pkcs7.encryptOID = RSAk;
pkcs7.hashOID = SHA256h;
pkcs7.encryptOID = (alg == TPM_ALG_RSA) ? RSAk : ECDSAk;
pkcs7.hashOID = wc_HashGetOID(hashType);
pkcs7.rng = wolfTPM2_GetRng(dev);
/* pass public key instead of private here. The PKCS7 will try a public
* key decode if using crypto callbacks */
pkcs7.privateKey = derPubKey->buffer;
pkcs7.privateKeySz = derPubKey->size;
rc = wc_PKCS7_EncodeSignedData(&pkcs7, output, sizeof(output));
if (rc <= 0) goto exit;
@ -261,7 +275,7 @@ static int PKCS7_SignVerify(WOLFTPM2_DEV* dev, int tpmDevId, WOLFTPM2_BUFFER* de
TPM2_PrintBin(output, outputSz);
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
pemFile = XFOPEN("./examples/pkcs7/pkcs7tpmsigned.p7s", "wb");
pemFile = XFOPEN(outFile, "wb");
if (pemFile != XBADFILE) {
rc = (int)XFWRITE(output, 1, outputSz, pemFile);
XFCLOSE(pemFile);
@ -297,6 +311,16 @@ exit:
return rc;
}
static void usage(void)
{
printf("Expected usage:\n");
printf("./examples/pkcs7/pkcs7 [-ecc/-rsa] [-out=]\n");
printf("* -ecc/-rsa: Use RSA or ECC key (default is RSA)\n");
printf("* -incert=file: Certificate for key used\n");
printf("\tDefault: RSA=./certs/client-rsa-cert.der, ECC=./certs/client-ecc-cert.der\n");
printf("* -out=file: Generated PKCS7 file containing signed data and certificate\n");
}
int TPM2_PKCS7_Example(void* userCtx)
{
return TPM2_PKCS7_ExampleArgs(userCtx, 0, NULL);
@ -306,22 +330,60 @@ int TPM2_PKCS7_ExampleArgs(void* userCtx, int argc, char *argv[])
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storageKey;
WOLFTPM2_KEY rsaKey;
WOLFTPM2_KEY tpmKey;
TPMT_PUBLIC publicTemplate;
TpmCryptoDevCtx tpmCtx;
int tpmDevId;
WOLFTPM2_BUFFER der;
WOLFTPM2_BUFFER derCert;
WOLFTPM2_BUFFER derPubKey;
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
XFILE derFile;
const char* inCert = NULL;
#endif
TPM_ALG_ID alg = TPM_ALG_RSA;
const char* outFile = "./examples/pkcs7/pkcs7tpmsigned.p7s";
const char* outFileEx = "./examples/pkcs7/pkcs7tpmsignedex.p7s";
enum wc_HashType hashType = WC_HASH_TYPE_SHA256;
(void)argc;
(void)argv;
if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
XSTRCMP(argv[1], "-h") == 0 ||
XSTRCMP(argv[1], "--help") == 0) {
usage();
return 0;
}
}
while (argc > 1) {
if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
alg = TPM_ALG_ECC;
}
else if (XSTRCMP(argv[argc-1], "-rsa") == 0) {
alg = TPM_ALG_RSA;
}
else if (XSTRNCMP(argv[argc-1], "-incert=",
XSTRLEN("-incert=")) == 0) {
inCert = argv[argc-1] + XSTRLEN("-incert=");
}
else if (XSTRNCMP(argv[argc-1], "-out=",
XSTRLEN("-out=")) == 0) {
outFile = argv[argc-1] + XSTRLEN("-out=");
}
else if (XSTRNCMP(argv[argc-1], "-outex=",
XSTRLEN("-outex=")) == 0) {
outFileEx = argv[argc-1] + XSTRLEN("-outex=");
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
argc--;
}
printf("TPM2 PKCS7 Example\n");
XMEMSET(&der, 0, sizeof(der));
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
XMEMSET(&derCert, 0, sizeof(derCert));
XMEMSET(&derPubKey, 0, sizeof(derPubKey));
XMEMSET(&tpmKey, 0, sizeof(tpmKey));
XMEMSET(&storageKey, 0, sizeof(storageKey));
/* Init the TPM2 device */
@ -331,60 +393,110 @@ int TPM2_PKCS7_ExampleArgs(void* userCtx, int argc, char *argv[])
/* Setup the wolf crypto device callback */
XMEMSET(&tpmCtx, 0, sizeof(tpmCtx));
#ifndef NO_RSA
tpmCtx.rsaKey = &rsaKey;
if (alg == TPM_ALG_RSA)
tpmCtx.rsaKey = &tpmKey;
#endif
#ifdef HAVE_ECC
if (alg == TPM_ALG_ECC)
tpmCtx.eccKey = &tpmKey;
#endif
rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx, &tpmDevId);
if (rc < 0) goto exit;
/* get SRK */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA);
rc = getPrimaryStoragekey(&dev, &storageKey, alg);
if (rc != 0) goto exit;
/* Create/Load RSA key for PKCS7 signing */
rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA);
if (rc != 0) goto exit;
/* Create/Load key for PKCS7 signing */
if (alg == TPM_ALG_RSA) {
rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA);
if (rc == 0) {
rc = getRSAkey(&dev,
&storageKey,
&tpmKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
}
if (rc == 0) {
/* export public key as DER for PKCS7, so it has the key information */
rc = getRSAkey(&dev,
&storageKey,
&rsaKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
if (rc != 0) goto exit;
wolfTPM2_SetAuthHandle(&dev, 0, &rsaKey.handle);
}
}
else {
TPM_ECC_CURVE curve;
#if defined(NO_ECC256) && defined(HAVE_ECC384) && ECC_MIN_KEY_SZ <= 384
/* make sure we use a curve that is enabled */
curve = TPM_ECC_NIST_P384;
#else
curve = TPM_ECC_NIST_P256;
#endif
rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
curve, TPM_ALG_ECDSA);
if (rc == 0) {
rc = getECCkey(&dev,
&storageKey,
&tpmKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
}
if (rc == 0) {
/* export public key as DER for PKCS7, so it has the key information */
}
}
if (rc != 0) goto exit;
wolfTPM2_SetAuthHandle(&dev, 0, &tpmKey.handle);
/* load DER certificate for TPM key (obtained by running
`./examples/csr/csr` and `./certs/certreq.sh`) */
* `./examples/csr/csr` and `./certs/certreq.sh`) */
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
derFile = XFOPEN("./certs/client-rsa-cert.der", "rb");
if (inCert == NULL) {
if (alg == TPM_ALG_RSA)
inCert = "./certs/client-rsa-cert.der";
else
inCert = "./certs/client-ecc-cert.der";
}
derFile = XFOPEN(inCert, "rb");
if (derFile != XBADFILE) {
XFSEEK(derFile, 0, XSEEK_END);
der.size = (int)XFTELL(derFile);
derCert.size = (int)XFTELL(derFile);
XREWIND(derFile);
if (der.size > (int)sizeof(der.buffer)) {
if (derCert.size > (int)sizeof(derCert.buffer)) {
rc = BUFFER_E;
}
else {
rc = (int)XFREAD(der.buffer, 1, der.size, derFile);
rc = (rc == der.size) ? 0 : -1;
rc = (int)XFREAD(derCert.buffer, 1, derCert.size, derFile);
rc = (rc == derCert.size) ? 0 : -1;
}
XFCLOSE(derFile);
if (rc != 0) goto exit;
}
#endif
/* Export TPM public key as DER/ASN.1 (should match certificate) */
derPubKey.size = (int)sizeof(derPubKey.buffer);
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, &tpmKey,
ENCODING_TYPE_ASN1, derPubKey.buffer, (word32*)&derPubKey.size);
if (rc != 0) goto exit;
/* PKCS 7 sign/verify example */
rc = PKCS7_SignVerify(&dev, tpmDevId, &der);
rc = PKCS7_SignVerify(&dev, tpmDevId, &derCert, &derPubKey, alg, hashType,
outFile);
if (rc != 0) goto exit;
#ifdef ENABLE_PKCS7EX_EXAMPLE
/* PKCS 7 large data sign/verify example */
rc = PKCS7_SignVerifyEx(&dev, tpmDevId, &der);
rc = PKCS7_SignVerifyEx(&dev, tpmDevId, &derCert, &derPubKey, alg, hashType,
outFileEx);
if (rc != 0) goto exit;
#endif
@ -394,7 +506,7 @@ exit:
printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc));
}
wolfTPM2_UnloadHandle(&dev, &rsaKey.handle);
wolfTPM2_UnloadHandle(&dev, &tpmKey.handle);
wolfTPM2_Cleanup(&dev);

View File

@ -187,6 +187,10 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
./examples/pkcs7/pkcs7 >> run.out
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "pkcs7 failed! $RESULT" && exit 1
./examples/pkcs7/pkcs7 -ecc >> run.out
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "pkcs7 ecc failed! $RESULT" && exit 1
fi
# TLS Tests

View File

@ -103,11 +103,9 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
WOLFTPM2_KEY storageKey;
#ifndef NO_RSA
WOLFTPM2_KEY rsaKey;
RsaKey wolfRsaKey;
#endif
#ifdef HAVE_ECC
WOLFTPM2_KEY eccKey;
ecc_key wolfEccKey;
#ifndef WOLFTPM2_USE_SW_ECDHE
WOLFTPM2_KEY ecdhKey;
#endif
@ -141,11 +139,9 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
XMEMSET(&tpmCtx, 0, sizeof(tpmCtx));
#ifndef NO_RSA
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
XMEMSET(&wolfRsaKey, 0, sizeof(wolfRsaKey));
#endif
#ifdef HAVE_ECC
XMEMSET(&eccKey, 0, sizeof(eccKey));
XMEMSET(&wolfEccKey, 0, sizeof(wolfEccKey));
#ifndef WOLFTPM2_USE_SW_ECDHE
/* Ephemeral Key */
XMEMSET(&ecdhKey, 0, sizeof(ecdhKey));
@ -222,7 +218,8 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
}
#endif
/* See if primary storage key already exists */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA);
rc = getPrimaryStoragekey(&dev, &storageKey,
useECC ? TPM_ALG_ECC : TPM_ALG_RSA);
if (rc != 0) goto exit;
/* Start an authenticated session (salted / unbound) with parameter encryption */
@ -250,7 +247,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
rc = getRSAkey(&dev,
&storageKey,
&rsaKey,
&wolfRsaKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
@ -269,7 +266,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
rc = getECCkey(&dev,
&storageKey,
&eccKey,
&wolfEccKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
@ -377,17 +374,16 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
* public key instead (if crypto callbacks are enabled).
*/
#ifndef NO_TLS_MUTUAL_AUTH
if (!useECC) {
#ifndef NO_RSA
byte der[1024];
word32 derSz = sizeof(der);
rc = wc_RsaKeyToPublicDer_ex(&wolfRsaKey, der, derSz, 1);
{
/* Export TPM public key as DER */
byte der[1024];
word32 derSz = (word32)sizeof(der);
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, !useECC ? &rsaKey : &eccKey,
ENCODING_TYPE_ASN1, der, &derSz);
if (rc < 0) {
printf("Failed to export RSA public key!\n");
goto exit;
}
derSz = rc;
rc = 0;
/* Private key only exists on the TPM and crypto callbacks are used for
* signing. Public key is required to enable TLS client (mutual auth).
@ -397,37 +393,6 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
printf("Failed to set RSA key!\n");
goto exit;
}
#else
printf("Error: RSA not compiled in\n");
rc = -1;
goto exit;
#endif /* !NO_RSA */
}
else {
#ifdef HAVE_ECC
byte der[256];
word32 derSz = sizeof(der);
rc = wc_EccPublicKeyToDer(&wolfEccKey, der, derSz, 1);
if (rc < 0) {
printf("Failed to export ECC public key!\n");
goto exit;
}
derSz = rc;
rc = 0;
/* Private key only exists on the TPM and crypto callbacks are used for
* signing. Public key is required to enable TLS client (mutual auth).
* This API accepts public keys when crypto callbacks are enabled */
if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
printf("Failed to set ECC key!\n");
goto exit;
}
#else
printf("RSA not supported in this build\n");
rc = -1;
goto exit;
#endif /* HAVE_ECC */
}
/* Client Certificate (Mutual Authentication) */
@ -611,11 +576,9 @@ exit:
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
#ifndef NO_RSA
wc_FreeRsaKey(&wolfRsaKey);
wolfTPM2_UnloadHandle(&dev, &rsaKey.handle);
#endif
#ifdef HAVE_ECC
wc_ecc_free(&wolfEccKey);
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
#ifndef WOLFTPM2_USE_SW_ECDHE
wolfTPM2_UnloadHandle(&dev, &ecdhKey.handle);

View File

@ -101,11 +101,9 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
WOLFTPM2_KEY storageKey;
#ifndef NO_RSA
WOLFTPM2_KEY rsaKey;
RsaKey wolfRsaKey;
#endif
#ifdef HAVE_ECC
WOLFTPM2_KEY eccKey;
ecc_key wolfEccKey;
#ifndef WOLFTPM2_USE_SW_ECDHE
WOLFTPM2_KEY ecdhKey;
#endif
@ -152,11 +150,9 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
XMEMSET(&tpmCtx, 0, sizeof(tpmCtx));
#ifndef NO_RSA
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
XMEMSET(&wolfRsaKey, 0, sizeof(wolfRsaKey));
#endif
#ifdef HAVE_ECC
XMEMSET(&eccKey, 0, sizeof(eccKey));
XMEMSET(&wolfEccKey, 0, sizeof(wolfEccKey));
#ifndef WOLFTPM2_USE_SW_ECDHE
/* Ephemeral Key */
XMEMSET(&ecdhKey, 0, sizeof(ecdhKey));
@ -239,7 +235,8 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
}
#endif
/* See if primary storage key already exists */
rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA);
rc = getPrimaryStoragekey(&dev, &storageKey,
useECC ? TPM_ALG_ECC : TPM_ALG_RSA);
if (rc != 0) goto exit;
/* Start an authenticated session (salted / unbound) with parameter encryption */
@ -267,7 +264,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
rc = getRSAkey(&dev,
&storageKey,
&rsaKey,
&wolfRsaKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
@ -286,7 +283,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
rc = getECCkey(&dev,
&storageKey,
&eccKey,
&wolfEccKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
@ -384,11 +381,30 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
}
#endif
#else
{
/* Export TPM public key as DER */
byte der[1024];
word32 derSz = (word32)sizeof(der);
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, !useECC ? &rsaKey : &eccKey,
ENCODING_TYPE_ASN1, der, &derSz);
if (rc < 0) {
printf("Failed to export TPM public key!\n");
goto exit;
}
/* Private key only exists on the TPM and crypto callbacks are used for
* signing. Public key is required to enable TLS client (mutual auth).
* This API accepts public keys when crypto callbacks are enabled */
if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
printf("Failed to set RSA key!\n");
goto exit;
}
}
/* Server certificate */
if (!useECC) {
#ifndef NO_RSA
byte der[1024];
word32 derSz = sizeof(der);
const char* useCert = "./certs/server-rsa-cert.pem";
if (useSelfSign) {
useCert = "./certs/tpm-rsa-cert.pem";
@ -401,23 +417,6 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
printf("Error loading RSA client cert\n");
goto exit;
}
rc = wc_RsaKeyToPublicDer_ex(&wolfRsaKey, der, derSz, 1);
if (rc < 0) {
printf("Failed to export RSA public key!\n");
goto exit;
}
derSz = rc;
rc = 0;
/* Private key only exists on the TPM and crypto callbacks are used for
* signing. Public key is required to enable TLS client (mutual auth).
* This API accepts public keys when crypto callbacks are enabled */
if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
printf("Failed to set RSA key!\r\n");
goto exit;
}
#else
printf("Error: RSA not compiled in\n");
rc = -1;
@ -426,8 +425,6 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
}
else {
#ifdef HAVE_ECC
byte der[256];
word32 derSz = sizeof(der);
const char* useCert = "./certs/server-ecc-cert.pem";
if (useSelfSign) {
useCert = "./certs/tpm-ecc-cert.pem";
@ -440,23 +437,6 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
printf("Error loading ECC client cert\n");
goto exit;
}
rc = wc_EccPublicKeyToDer(&wolfEccKey, der, derSz, 1);
if (rc < 0) {
printf("Failed to export ECC public key!\n");
goto exit;
}
derSz = rc;
rc = 0;
/* Private key only exists on the TPM and crypto callbacks are used for
* signing. Public key is required to enable TLS server auth.
* This API accepts public keys when crypto callbacks are enabled */
if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
printf("Failed to set ECC key!\n");
goto exit;
}
#else
printf("Error: ECC not compiled in\n");
rc = -1;
@ -611,11 +591,9 @@ exit:
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
#ifndef NO_RSA
wc_FreeRsaKey(&wolfRsaKey);
wolfTPM2_UnloadHandle(&dev, &rsaKey.handle);
#endif
#ifdef HAVE_ECC
wc_ecc_free(&wolfEccKey);
wolfTPM2_UnloadHandle(&dev, &eccKey.handle);
#ifndef WOLFTPM2_USE_SW_ECDHE
wolfTPM2_UnloadHandle(&dev, &ecdhKey.handle);

View File

@ -248,8 +248,14 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
word32 rsLen = sizeof(sigRS), keySz;
word32 inlen = info->pk.eccsign.inlen;
/* truncate input to match key size */
/* get key size from wolf signing key */
keySz = wc_ecc_size(info->pk.eccsign.key);
if (keySz == 0) {
/* if not populated fallback to key size for TPM key */
keySz = TPM2_GetCurveSize(
tlsCtx->eccKey->pub.publicArea.parameters.eccDetail.curveID);
}
/* truncate input to match key size */
if (inlen > keySz)
inlen = keySz;

View File

@ -2729,6 +2729,107 @@ int wolfTPM2_DecodeEccDer(const byte* der, word32 derSz, TPM2B_PUBLIC* pub,
}
#endif /* HAVE_ECC */
int wolfTPM2_ExportPublicKeyBuffer(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
int encodingType, byte* out, word32* outSz)
{
int rc;
word32 derSz = 0;
union keyUnion {
#ifndef NO_RSA
RsaKey rsa;
#endif
#ifdef HAVE_ECC
ecc_key ecc;
#endif
} key;
if (dev == NULL || tpmKey == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(&key, 0, sizeof(key));
/* determine the type of key in WOLFTPM2_KEY */
if (tpmKey->pub.publicArea.type == TPM_ALG_ECC) {
#ifdef HAVE_ECC
rc = wc_ecc_init(&key.ecc);
if (rc == 0) {
/* load public portion of key into wolf ECC Key */
rc = wolfTPM2_EccKey_TpmToWolf(dev, tpmKey, &key.ecc);
if (rc == 0) {
rc = wc_EccPublicKeyToDer(&key.ecc, out, *outSz, 1);
if (rc > 0) {
derSz = rc;
rc = 0;
}
else {
rc = BUFFER_E;
}
}
}
#else
rc = NOT_COMPILED_IN;
#endif
}
else if (tpmKey->pub.publicArea.type == TPM_ALG_RSA) {
#ifndef NO_RSA
rc = wc_InitRsaKey(&key.rsa, NULL);
if (rc == 0) {
/* load public portion of key into wolf RSA Key */
rc = wolfTPM2_RsaKey_TpmToWolf(dev, tpmKey, &key.rsa);
if (rc == 0) {
rc = wc_RsaKeyToPublicDer_ex(&key.rsa, out, *outSz, 1);
if (rc > 0) {
derSz = rc;
rc = 0;
}
else {
rc = BUFFER_E;
}
}
}
#else
rc = NOT_COMPILED_IN;
#endif
}
else {
#ifdef DEBUG_WOLFTPM
printf("Invalid tpmKey type!\n");
#endif
rc = BAD_FUNC_ARG;
}
/* Optionally convert to PEM */
if (rc == 0 && encodingType == ENCODING_TYPE_PEM) {
#ifdef WOLFSSL_DER_TO_PEM
WOLFTPM2_BUFFER tmp;
if (derSz > (word32)sizeof(tmp.buffer)) {
rc = BUFFER_E;
}
else {
/* move DER to temp variable */
tmp.size = derSz;
XMEMCPY(tmp.buffer, out, derSz);
XMEMSET(out, 0, *outSz);
rc = wc_DerToPem(tmp.buffer, tmp.size, out, *outSz, PUBLICKEY_TYPE);
if (rc > 0) {
*outSz = rc;
rc = 0;
}
else {
rc = BUFFER_E;
}
}
#else
rc = NOT_COMPILED_IN;
#endif
}
else if (rc == 0) {
*outSz = derSz;
}
return rc;
}
int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType,
WOLFTPM2_KEY* key, int encodingType, const char* input, word32 inSz,
TPMA_OBJECT objectAttributes)
@ -2991,61 +3092,8 @@ int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
int wolfTPM2_RsaKey_TpmToPemPub(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
byte* pem, word32* pemSz)
{
int rc = TPM_RC_FAILURE;
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_DER_TO_PEM) && \
(defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA)
RsaKey rsaKey;
byte* derBuf = NULL;
int derSz = 0;
#endif
if (dev == NULL || tpmKey == NULL || pem == NULL || pemSz == NULL)
return BAD_FUNC_ARG;
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_DER_TO_PEM) && \
(defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA)
/* Prepare wolfCrypt key structure */
rc = wc_InitRsaKey(&rsaKey, NULL);
if (rc == 0) {
/* Convert the wolfTPM key to wolfCrypt format */
rc = wolfTPM2_RsaKey_TpmToWolf(dev, tpmKey, &rsaKey);
if (rc == 0) {
/* Get DER size - newer API can be called with NULL to get size */
rc = wc_RsaKeyToPublicDer(&rsaKey, NULL, 0);
if (rc > 0) {
derSz = rc;
rc = 0;
}
else if (rc == BAD_FUNC_ARG) {
/* for older wolfSSL estimate based on key size */
derSz = wc_RsaEncryptSize(&rsaKey) * 2;
rc = 0;
}
}
if (derSz > 0) {
derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (derBuf == NULL)
rc = MEMORY_E;
}
if (rc == 0) {
/* Convert the wolfCrypt key to DER format */
rc = wc_RsaKeyToPublicDer(&rsaKey, derBuf, derSz);
}
if (rc >= 0) {
/* Convert the DER key to PEM format */
derSz = rc;
rc = wc_DerToPem(derBuf, derSz, pem, *pemSz, PUBLICKEY_TYPE);
}
if (rc >= 0) {
*pemSz = rc;
rc = TPM_RC_SUCCESS;
}
XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wc_FreeRsaKey(&rsaKey);
}
#endif
return rc;
return wolfTPM2_ExportPublicKeyBuffer(dev, tpmKey,
ENCODING_TYPE_PEM, pem, pemSz);
}
static word32 wolfTPM2_RsaKey_Exponent(byte* e, word32 eSz)

View File

@ -1189,6 +1189,24 @@ WOLFTPM_API int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType,
WOLFTPM2_KEY* key, int encodingType, const char* input, word32 inSz,
TPMA_OBJECT objectAttributes);
/*!
\ingroup wolfTPM2_Wrappers
\brief Helper function to export a TPM RSA/ECC public key with PEM/DER formatting
\return TPM_RC_SUCCESS: successful - populates key->pub
\return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code)
\return BUFFER_E: insufficient space in provided buffer
\return BAD_FUNC_ARG: check the provided arguments
\param dev pointer to a TPM2_DEV struct
\param tpmKey pointer to a WOLFTPM2_KEY with populated key
\param encodingType ENCODING_TYPE_PEM or ENCODING_TYPE_ASN1 (DER)
\param out buffer to export public key
\param outSz pointer to length of the out buffer
*/
WOLFTPM_API int wolfTPM2_ExportPublicKeyBuffer(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
int encodingType, byte* out, word32* outSz);
#ifndef NO_RSA
/*!
\ingroup wolfTPM2_Wrappers
@ -1252,8 +1270,8 @@ WOLFTPM_API int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKe
/*!
\ingroup wolfTPM2_Wrappers
\brief Convert a public RSA TPM key to PEM format public key
Note: pem and tempBuf must be different buffers, of equal size
\brief Convert a public RSA TPM key to PEM format public key.
Note: This API is a wrapper around wolfTPM2_ExportPublicKeyBuffer
\return TPM_RC_SUCCESS: successful
\return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code)
@ -1264,6 +1282,7 @@ WOLFTPM_API int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKe
\param pem pointer to an array of byte type, used as temporary storage for PEM conversation
\param pemSz pointer to integer variable, to store the used buffer size
\sa wolfTPM2_ExportPublicKeyBuffer
\sa wolfTPM2_RsaKey_TpmToWolf
\sa wolfTPM2_RsaKey_WolfToTpm
*/