From 8455beaae4656d4a4deef7133ac97a726c841971 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 12 Jul 2021 17:12:22 -0700 Subject: [PATCH] Fixes for Public PEM functions. Cleanups. --- .gitignore | 10 +- examples/attestation/README.md | 6 -- examples/attestation/activate_credential.c | 3 +- examples/attestation/make_credential.c | 6 +- examples/keygen/keygen.c | 47 ++++----- src/tpm2_wrap.c | 111 +++++++++++++++------ wolftpm/tpm2_wrap.h | 13 +-- 7 files changed, 121 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index 9855d219..4179de0d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,8 +26,10 @@ src/.deps src/.libs RemoteSystemsTempFiles *.o +*.dep *.deps *.libs +IDE/IAR-EWARM/settings wolftpm/options.h examples/wrap/wrap_test @@ -75,12 +77,16 @@ certs/server-*.pem certs/client-*.der certs/client-*.pem certs/serial.old -*.dep -IDE/IAR-EWARM/settings + +# Test files quote.blob keyblob.bin ecc_test_blob.raw rsa_test_blob.raw +ak.name +cred.blob +ek.pub +srk.pub # Generated Documentation docs/html diff --git a/examples/attestation/README.md b/examples/attestation/README.md index cc805aba..0a7c258e 100644 --- a/examples/attestation/README.md +++ b/examples/attestation/README.md @@ -43,7 +43,6 @@ Note: Using the `keygen` example we can create the necessary TPM 2.0 Attestation Key and TPM 2.0 Primary Storage Key that will be used as a Primary Attestation Key(PAK). ``` - $ ./examples/keygen/keygen -rsa TPM2.0 Key generation example Key Blob: keyblob.bin @@ -55,7 +54,6 @@ RSA AIK template Creating new RSA key... Created new key (pub 280, priv 222 bytes) Wrote 508 bytes to keyblob.bin - ``` ### Make Credential Example Usage @@ -63,7 +61,6 @@ Wrote 508 bytes to keyblob.bin Using the `make_credential` example an attestation server can generate remote attestation challenge. The secret is 32 bytes of randomly generated seed that could be used for a symmetric key in some remote attestation schemes. ``` - $ ./examples/attestation/make_credential Using default values Demo how to create a credential blob for remote attestation @@ -74,7 +71,6 @@ Reading the private part of the key AK loaded at 0x80000001 TPM2_MakeCredential success Wrote credential blob and secret to cred.blob, 514 bytes - ``` The transfer of the PAK and AK public parts between the client and attestation server is not part of the `make_credential` example, because the exchange is implementation specific. @@ -84,7 +80,6 @@ The transfer of the PAK and AK public parts between the client and attestation s Using the `activate_credential` example a client can decrypt the remote attestation challenge. The secret will be exposed in plain and can be exchanged with the attestation server. ``` - $ ./examples/attestation/activate_credential Using default values Demo how to create a credential blob for remote attestation @@ -99,7 +94,6 @@ TPM2_StartAuthSession: sessionHandle 0x3000000 TPM2_policyCommandCode success Read credential blob and secret from cred.blob, 514 bytes TPM2_ActivateCredential success - ``` The transfer of the challenge response containing the secret in plain (or used as a symmetric key seed) is not part of the `activate_credential` example, because the exchange is also implementation specific. diff --git a/examples/attestation/activate_credential.c b/examples/attestation/activate_credential.c index 9f8f7ed2..0dd7cb1e 100644 --- a/examples/attestation/activate_credential.c +++ b/examples/attestation/activate_credential.c @@ -182,7 +182,8 @@ int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) sizeof(cmdIn.activCred.secret), fp); XFCLOSE(fp); } - printf("Read credential blob and secret from %s, %d bytes\n", input, dataSize); + printf("Read credential blob and secret from %s, %d bytes\n", + input, dataSize); #else printf("Can not load credential. File support not enabled\n"); goto exit; diff --git a/examples/attestation/make_credential.c b/examples/attestation/make_credential.c index 011143c1..3238c891 100644 --- a/examples/attestation/make_credential.c +++ b/examples/attestation/make_credential.c @@ -129,7 +129,8 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) goto exit; } /* Prepare the key for use by the TPM */ - XMEMCPY(&cmdIn.loadExtIn.inPublic, &primary.pub, sizeof(cmdIn.loadExtIn.inPublic)); + XMEMCPY(&cmdIn.loadExtIn.inPublic, &primary.pub, + sizeof(cmdIn.loadExtIn.inPublic)); cmdIn.loadExtIn.hierarchy = TPM_RH_NULL; rc = TPM2_LoadExternal(&cmdIn.loadExtIn, &cmdOut.loadExtOut); if (rc != TPM_RC_SUCCESS) { @@ -175,7 +176,8 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) sizeof(cmdOut.makeCred.secret), fp); XFCLOSE(fp); } - printf("Wrote credential blob and secret to %s, %d bytes\n", output, dataSize); + printf("Wrote credential blob and secret to %s, %d bytes\n", + output, dataSize); #else printf("Can not store credential. File support not enabled\n"); #endif diff --git a/examples/keygen/keygen.c b/examples/keygen/keygen.c index 469fd9ba..00ac8d07 100644 --- a/examples/keygen/keygen.c +++ b/examples/keygen/keygen.c @@ -101,7 +101,7 @@ static int symChoice(const char* arg, TPM_ALG_ID* algSym, int* keyBits, } *keyBits = atoi(&arg[SYM_EXTRA_OPTS_KEY_BITS_POS]); - if(*keyBits != 128 && *keyBits != 192 && *keyBits != 256) { + if (*keyBits != 128 && *keyBits != 192 && *keyBits != 256) { return TPM_RC_FAILURE; } @@ -116,7 +116,6 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) WOLFTPM2_KEY storage; /* SRK */ WOLFTPM2_KEY *primary = NULL; WOLFTPM2_KEY aesKey; /* Symmetric key */ - WOLFTPM2_KEY newKey; /* child or attestation key */ WOLFTPM2_KEYBLOB newKeyBlob; /* newKey as WOLFTPM2_KEYBLOB */ WOLFTPM2_KEYBLOB primaryBlob; /* Primary key as WOLFTPM2_KEYBLOB */ TPMT_PUBLIC publicTemplate; @@ -194,7 +193,6 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) XMEMSET(&endorse, 0, sizeof(endorse)); XMEMSET(&storage, 0, sizeof(storage)); XMEMSET(&aesKey, 0, sizeof(aesKey)); - XMEMSET(&newKey, 0, sizeof(newKey)); XMEMSET(&newKeyBlob, 0, sizeof(newKeyBlob)); XMEMSET(&primaryBlob, 0, sizeof(primaryBlob)); XMEMSET(&tpmSession, 0, sizeof(tpmSession)); @@ -215,7 +213,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) goto exit; } - if(endorseKey) { + if (endorseKey) { rc = wolfTPM2_CreateEK(&dev, &endorse, TPM_ALG_RSA); endorse.handle.policyAuth = 1; /* EK requires Policy auth, not Password */ pubFilename = ekPubFile; @@ -329,7 +327,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) } } #else - if(alg == TPM_ALG_SYMCIPHER) { + if (alg == TPM_ALG_SYMCIPHER) { printf("The Public Part of a symmetric key contains only meta data\n"); } printf("Key Public Blob %d\n", newKeyBlob.pub.size); @@ -341,32 +339,31 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) /* Save EK public key as PEM format file to the disk */ #if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) if (pemFiles) { - byte pem[MAX_RSA_KEY_BYTES], tempBuf[MAX_RSA_KEY_BYTES]; - int pemSz, tempSz = sizeof(tempBuf); + byte pem[MAX_RSA_KEY_BYTES]; + word32 pemSz; - if (endorseKey) { - pemFilename = pemFileEk; - } - else { - pemFilename = pemFileSrk; - } - - rc = wolfTPM2_RsaKey_TpmToPem(&dev, primary, pem, &pemSz, tempBuf, tempSz); + pemFilename = (endorseKey) ? pemFileEk : pemFileSrk; + pemSz = (word32)sizeof(pem); + rc = wolfTPM2_RsaKey_TpmToPemPub(&dev, primary, pem, &pemSz); if (rc == 0) { - rc = writeKeyPubPem(pemFilename, pem, (word32)pemSz); + rc = writeKeyPubPem(pemFilename, pem, pemSz); } - if (bAIK) { - pemFilename = pemFileAk; - } - else { - pemFilename = pemFileKey; - } - - rc = wolfTPM2_RsaKey_TpmToPem(&dev, &newKey, pem, &pemSz, tempBuf, tempSz); + pemFilename = (bAIK) ? pemFileAk : pemFileKey; + pemSz = (word32)sizeof(pem); + rc = wolfTPM2_RsaKey_TpmToPemPub(&dev, (WOLFTPM2_KEY*)&newKeyBlob, + pem, &pemSz); if (rc == 0) { - rc = writeKeyPubPem(pemFilename, pem, (word32)pemSz); + rc = writeKeyPubPem(pemFilename, pem, pemSz); } + wolfTPM2_UnloadHandle(&dev, &newKeyBlob.handle); + + #if 0 + /* example for loading public pem to TPM */ + rc = wolfTPM2_RsaKey_PubPemToTpm(&dev, (WOLFTPM2_KEY*)&newKeyBlob, pem, pemSz); + printf("wolfTPM2_RsaKey_PubPemToTpm rc=%d\n", rc); + rc = 0; + #endif } #else printf("Unable to store EK pub as PEM file. Lack of file support\n"); diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 3a1403dd..71e0aeb9 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -1784,29 +1784,58 @@ int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, return rc; } -int wolfTPM2_RsaKey_TpmToPem(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, - byte* pem, int* pemSz, byte* tempBuf, int tempSz) +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) - int derSz; 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) /* Prepare wolfCrypt key structure */ rc = wc_InitRsaKey(&rsaKey, NULL); - if (rc != 0) return rc; - /* Convert the wolfTPM key to wolfCrypt format */ - rc = wolfTPM2_RsaKey_TpmToWolf(dev, tpmKey, &rsaKey); - if (rc != 0) return rc; - /* Convert the wolfCrypt key to DER format */ - rc = wc_RsaKeyToPublicDer(&rsaKey, tempBuf, tempSz); - if (rc <= 0) return rc; - derSz = rc; - /* Convert the DER key to PEM format */ - rc = wc_DerToPem(tempBuf, derSz, pem, tempSz, PUBLICKEY_TYPE); - if (rc <= 0) return rc; - *pemSz = rc; - rc = TPM_RC_SUCCESS; + 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; + } + 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; } @@ -1878,27 +1907,49 @@ int wolfTPM2_RsaKey_WolfToTpm(WOLFTPM2_DEV* dev, RsaKey* wolfKey, } int wolfTPM2_RsaKey_PubPemToTpm(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, - byte* pem, int pemSz, byte* tempBuf, int tempSz) + const byte* pem, word32 pemSz) { int rc = TPM_RC_FAILURE; -#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_CERT_EXT) && \ - defined(WOLFSSL_PUB_PEM_TO_DER) && defined(WOLFSSL_PEM_TO_DER) - word32 idx; +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_PEM_TO_DER) && \ + (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) RsaKey rsaKey; +#endif + if (dev == NULL || tpmKey == NULL || pem == NULL) + return BAD_FUNC_ARG; + +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_PEM_TO_DER) && \ + (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) /* Prepare wolfCrypt key structure */ rc = wc_InitRsaKey(&rsaKey, NULL); - if (rc != 0) return rc; - /* Convert PEM format key from file to DER */ - rc = wc_PubKeyPemToDer(pem, pemSz, tempBuf, tempSz); - if (rc != 0) return rc; - /* Convert DER to wolfCrypt file */ - idx = 0; - rc = wc_RsaPublicKeyDecode(tempBuf, &idx, &rsaKey, tempSz); - if (rc != 0) return rc; - /* Load into the TPM */ - rc = wolfTPM2_RsaKey_WolfToTpm(dev, &rsaKey, tpmKey); + if (rc == 0) { + /* allocate buffer for DER */ + word32 derSz = pemSz; /* DER is always smaller */ + byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + rc = MEMORY_E; + } + if (rc == 0) { + /* Convert PEM format key from file to DER - inline okay */ + rc = wc_PubKeyPemToDer(pem, pemSz, derBuf, derSz); + } + if (rc >= 0) { + /* Convert DER to wolfCrypt file */ + word32 idx = 0; + derSz = (word32)rc; + rc = wc_RsaPublicKeyDecode(derBuf, &idx, &rsaKey, derSz); + } + if (rc == 0) { + /* Load into the TPM */ + rc = wolfTPM2_RsaKey_WolfToTpm(dev, &rsaKey, tpmKey); + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsaKey); + } +#else + (void)pemSz; #endif + return rc; } #endif /* !NO_RSA */ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 8da0f05b..b46e5168 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -1042,16 +1042,13 @@ WOLFTPM_API int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKe \param keyBlob pointer to a struct of WOLFTPM2_KEY type, holding a TPM key \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 - \param tempBuf pointer to an array of byte type, used as temporary storage for conversation - \param tempSz integer, specifying the size of the tempSz \sa wolfTPM2_RsaKey_TpmToWolf \sa wolfTPM2_RsaKey_WolfToTpm */ -WOLFTPM_API int wolfTPM2_RsaKey_TpmToPem(WOLFTPM2_DEV* dev, +WOLFTPM_API int wolfTPM2_RsaKey_TpmToPemPub(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* keyBlob, - byte* pem, int* pemSz, - byte* tempBuf, int tempSz); + byte* pem, word32* pemSz); /*! \ingroup wolfTPM2_Wrappers @@ -1102,15 +1099,13 @@ WOLFTPM_API int wolfTPM2_RsaKey_WolfToTpm_ex(WOLFTPM2_DEV* dev, \param tpmKey pointer to an empty struct of WOLFTPM2_KEY type, to hold the imported TPM key \param pem pointer to an array of byte type, containing a PEM formated public key material \param pemSz pointer to integer variable, specifying the size of PEM key data - \param tempBuf pointer to an array of byte type, to be used as temporary storage - \param tempSz integer variable, specifying the size of the buffer \sa wolfTPM2_RsaKey_WolfToTpm \sa wolfTPM2_RsaKey_TpmToPem \sa wolfTPM2_RsaKey_TpmToWolf */ -int wolfTPM2_RsaKey_PubPemToTpm(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, - byte* pem, int pemSz, byte* tempBuf, int tempSz); +WOLFTPM_API int wolfTPM2_RsaKey_PubPemToTpm(WOLFTPM2_DEV* dev, + WOLFTPM2_KEY* tpmKey, const byte* pem, word32 pemSz); #endif #ifdef HAVE_ECC /*!