From 53b043dafa7ecf1b824b9f1394d2456a9417ee09 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 6 Dec 2023 09:05:08 -0800 Subject: [PATCH 1/2] Tests for keyblob buffer export/import. Added support for getting the keyblob sizes. --- examples/tpm_test_keys.c | 2 +- src/tpm2_wrap.c | 35 ++++++++++----- tests/unit_tests.c | 97 ++++++++++++++++++++++++++++++++++++++++ wolftpm/tpm2_wrap.h | 6 ++- 4 files changed, 126 insertions(+), 14 deletions(-) diff --git a/examples/tpm_test_keys.c b/examples/tpm_test_keys.c index b9a38b44..90f29676 100644 --- a/examples/tpm_test_keys.c +++ b/examples/tpm_test_keys.c @@ -48,7 +48,7 @@ int writeBin(const char* filename, const byte *buf, word32 bufSz) XFILE fp = NULL; size_t fileSz = 0; - fp = XFOPEN(filename, "wt"); + fp = XFOPEN(filename, "wb"); if (fp != XBADFILE) { fileSz = XFWRITE(buf, 1, bufSz, fp); /* sanity check */ diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 95f00cef..eb9bd345 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -310,14 +310,14 @@ TPM_HANDLE wolfTPM2_GetHandleValue(WOLFTPM2_HANDLE* handle) } int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, - WOLFTPM2_KEYBLOB* key) + WOLFTPM2_KEYBLOB* key) { int rc = 0; int sz = 0; byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)]; int pubAreaSize; - if ((buffer == NULL) || (bufferSz <= 0) || (key == NULL)) { + if (key == NULL) { return BAD_FUNC_ARG; } @@ -335,10 +335,19 @@ int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, return BUFFER_E; } - if (bufferSz < sizeof(key->pub.size) + sizeof(UINT16) + key->pub.size + - sizeof(UINT16) + key->priv.size) { + /* calculate actual size */ + sz = sizeof(key->pub.size) + sizeof(UINT16) + key->pub.size + + sizeof(UINT16) + key->priv.size; + + /* return size only */ + if (buffer == NULL) { + return sz; + + } + if ((int)bufferSz < sz) { return BUFFER_E; } + sz = 0; /* Write size marker for the public part */ XMEMCPY(buffer + sz, &key->pub.size, sizeof(key->pub.size)); @@ -353,8 +362,8 @@ int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, sz += sizeof(UINT16) + key->priv.size; #ifdef WOLFTPM_DEBUG_VERBOSE + printf("Get KeyBlob: %d bytes\n", (int)sz); TPM2_PrintBin(buffer, sz); - printf("Getting %d bytes\n", (int)sz); #endif return sz; @@ -368,9 +377,7 @@ int wolfTPM2_GetKeyBlobAsSeparateBuffers(byte* pubBuffer, word32* pubBufferSz, byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)]; int pubAreaSize; - if (pubBuffer == NULL || pubBufferSz == NULL || (*pubBufferSz <= 0) || - privBuffer == NULL || privBufferSz == NULL || (*privBufferSz <= 0) || - (key == NULL)) { + if (key == NULL || pubBufferSz == NULL || privBufferSz == NULL) { return BAD_FUNC_ARG; } @@ -388,6 +395,12 @@ int wolfTPM2_GetKeyBlobAsSeparateBuffers(byte* pubBuffer, word32* pubBufferSz, return BUFFER_E; } + if (pubBuffer == NULL || privBuffer == NULL) { + *privBufferSz = sizeof(UINT16) + key->priv.size; + *pubBufferSz = sizeof(key->pub.size) + sizeof(UINT16) + key->pub.size; + return LENGTH_ONLY_E; + } + if (*pubBufferSz < sizeof(key->pub.size) + sizeof(UINT16) + key->pub.size || *privBufferSz < sizeof(UINT16) + key->priv.size) { return BUFFER_E; @@ -410,11 +423,11 @@ int wolfTPM2_GetKeyBlobAsSeparateBuffers(byte* pubBuffer, word32* pubBufferSz, *privBufferSz += sizeof(UINT16) + key->priv.size; #ifdef WOLFTPM_DEBUG_VERBOSE + printf("Get KeyBlob public: %d bytes\n", (int)*pubBufferSz); TPM2_PrintBin(pubBuffer, *pubBufferSz); - printf("Getting %d bytes for public buffer\n", (int)*pubBufferSz); + printf("Get KeyBlob private: %d bytes\n", (int)*privBufferSz); TPM2_PrintBin(privBuffer, *privBufferSz); - printf("Getting %d bytes for private buffer\n", (int)*privBufferSz); #endif return sz; @@ -436,8 +449,8 @@ int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key, byte *buffer, XMEMSET(key, 0, sizeof(WOLFTPM2_KEYBLOB)); #ifdef WOLFTPM_DEBUG_VERBOSE + printf("Set KeyBlob: %d bytes\n", (int)bufferSz); TPM2_PrintBin(buffer, bufferSz); - printf("Setting %d bytes\n", (int)bufferSz); #endif if (bufferSz < done_reading + sizeof(key->pub.size)) { diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 1859ae16..c737f3fa 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -486,6 +486,101 @@ static void test_wolfTPM2_thread_local_storage(void) #endif /* HAVE_THREAD_LS && HAVE_PTHREAD */ } +/* Test creating key and exporting keyblob as buffer, + * importing and loading key. */ +static void test_wolfTPM2_KeyBlob(TPM_ALG_ID alg) +{ + int rc; + TPM_HANDLE handle; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY srk; + WOLFTPM2_KEYBLOB key; + WOLFTPM2_BUFFER blob; + TPMT_PUBLIC publicTemplate; + word32 privBufferSz, pubBufferSz; + + XMEMSET(&srk, 0, sizeof(srk)); + XMEMSET(&key, 0, sizeof(key)); + XMEMSET(&publicTemplate, 0, sizeof(publicTemplate)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL); + AssertIntEQ(rc, 0); + + if (alg == TPM_ALG_ECC) + handle = TPM2_DEMO_STORAGE_KEY_HANDLE; + else /* RSA */ + handle = TPM2_DEMO_STORAGE_EC_KEY_HANDLE; + + /* Load or create the SRK */ + rc = wolfTPM2_ReadPublicKey(&dev, &srk, handle); + if ((rc & RC_MAX_FMT1) == TPM_RC_HANDLE) { + rc = wolfTPM2_CreateSRK(&dev, &srk, alg, + (byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1); + AssertIntEQ(rc, 0); + } + else { + srk.handle.auth.size = sizeof(gStorageKeyAuth)-1; + XMEMCPY(srk.handle.auth.buffer, gStorageKeyAuth, srk.handle.auth.size); + } + + if (alg == TPM_ALG_ECC) { + rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA, + TPM_ECC_NIST_P256, TPM_ALG_NULL); + } + else { /* RSA */ + rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA); + } + AssertIntEQ(rc, 0); + + /* Create key under SRK and get encrypted private and public from TPM */ + rc = wolfTPM2_CreateKey(&dev, &key, &srk.handle, &publicTemplate, + (byte*)gKeyAuth, sizeof(gKeyAuth)-1); + AssertIntEQ(rc, 0); + + /* Test getting size only */ + rc = wolfTPM2_GetKeyBlobAsSeparateBuffers(NULL, &pubBufferSz, + NULL, &privBufferSz, &key); + AssertIntEQ(rc, LENGTH_ONLY_E); + + /* Test exporting private and public parts separately */ + rc = wolfTPM2_GetKeyBlobAsSeparateBuffers(blob.buffer, &pubBufferSz, + &blob.buffer[pubBufferSz], &privBufferSz, &key); + AssertIntEQ(rc, 0); + + /* Test getting size only */ + rc = wolfTPM2_GetKeyBlobAsBuffer(NULL, sizeof(blob.buffer), &key); + AssertIntGT(rc, 0); + + /* Export private and public key */ + rc = wolfTPM2_GetKeyBlobAsBuffer(blob.buffer, sizeof(blob.buffer), &key); + AssertIntGT(rc, 0); + blob.size = rc; + + /* Reset the originally created key */ + XMEMSET(&key, 0, sizeof(key)); + + /* Load key blob (private/public) from buffer */ + rc = wolfTPM2_SetKeyBlobFromBuffer(&key, blob.buffer, blob.size); + AssertIntEQ(rc, 0); + key.handle.auth.size = sizeof(gKeyAuth)-1; + XMEMCPY(key.handle.auth.buffer, gKeyAuth, key.handle.auth.size); + + /* Load key to TPM and get temp handle */ + rc = wolfTPM2_LoadKey(&dev, &key, &srk.handle); + AssertIntEQ(rc, 0); + + wolfTPM2_UnloadHandle(&dev, &key.handle); + wolfTPM2_UnloadHandle(&dev, &srk.handle); + wolfTPM2_Cleanup(&dev); + + printf("Test TPM Wrapper:\tKeyBlob %s:\t%s\n", + TPM2_GetAlgName(alg), rc == 0 ? "Passed" : "Failed"); +} + #endif /* !WOLFTPM2_NO_WRAPPER */ #ifndef NO_MAIN_DRIVER @@ -509,6 +604,8 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM_ImportPublicKey(); test_wolfTPM2_PCRPolicy(); #endif + test_wolfTPM2_KeyBlob(TPM_ALG_RSA); + test_wolfTPM2_KeyBlob(TPM_ALG_ECC); test_wolfTPM2_Cleanup(); test_wolfTPM2_thread_local_storage(); #endif /* !WOLFTPM2_NO_WRAPPER */ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 01577416..8c8c843b 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -3148,7 +3148,7 @@ WOLFTPM_API int wolfTPM2_SetKeyAuthPassword(WOLFTPM2_KEY *key, const byte* auth, \brief Marshal data from a keyblob to a binary buffer. This can be stored to disk for loading in a separate process or after power - cycling. + cycling. If buffer is not provided then size only will be returned. \return Positive integer (size of the output) \return BUFFER_E: insufficient space in provided buffer @@ -3168,11 +3168,13 @@ WOLFTPM_API int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, \brief Marshal data from a keyblob to a binary buffer. This can be stored to disk for loading in a separate process or after power - cycling. + cycling. If either buffer is NULL then the size will be returned for + each part. \return Positive integer (size of the output) \return BUFFER_E: insufficient space in provided buffer \return BAD_FUNC_ARG: check the provided arguments + \return LENGTH_ONLY_E: Returning length only (when either of the buffers is NULL) \param pubBuffer pointer to buffer in which to store the public part of the marshaled keyblob \param pubBufferSz pointer to the size of the above buffer From 4a48fb38826a125f90d828a30ef2bc6d17d8ee99 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 8 Dec 2023 12:00:01 -0800 Subject: [PATCH 2/2] Peer review cleanups. --- src/tpm2_wrap.c | 8 +++----- wolftpm/tpm2_wrap.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index eb9bd345..ea60560c 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -347,11 +347,10 @@ int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, if ((int)bufferSz < sz) { return BUFFER_E; } - sz = 0; /* Write size marker for the public part */ - XMEMCPY(buffer + sz, &key->pub.size, sizeof(key->pub.size)); - sz += sizeof(key->pub.size); + XMEMCPY(buffer, &key->pub.size, sizeof(key->pub.size)); + sz = sizeof(key->pub.size); /* Write the public part with bytes aligned */ XMEMCPY(buffer + sz, pubAreaBuffer, sizeof(UINT16) + key->pub.size); @@ -373,7 +372,6 @@ int wolfTPM2_GetKeyBlobAsSeparateBuffers(byte* pubBuffer, word32* pubBufferSz, byte* privBuffer, word32* privBufferSz, WOLFTPM2_KEYBLOB* key) { int rc = 0; - int sz = 0; byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)]; int pubAreaSize; @@ -430,7 +428,7 @@ int wolfTPM2_GetKeyBlobAsSeparateBuffers(byte* pubBuffer, word32* pubBufferSz, TPM2_PrintBin(privBuffer, *privBufferSz); #endif - return sz; + return TPM_RC_SUCCESS; } int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key, byte *buffer, diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 8c8c843b..7afa21b4 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -3171,7 +3171,7 @@ WOLFTPM_API int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz, cycling. If either buffer is NULL then the size will be returned for each part. - \return Positive integer (size of the output) + \return TPM_RC_SUCCESS: successful \return BUFFER_E: insufficient space in provided buffer \return BAD_FUNC_ARG: check the provided arguments \return LENGTH_ONLY_E: Returning length only (when either of the buffers is NULL)