Skip to content

Commit

Permalink
Merge pull request #315 from dgarske/keyblob_tests
Browse files Browse the repository at this point in the history
Added tests for keyblob buffer export/import and support for getting sizes
  • Loading branch information
embhorn authored Dec 8, 2023
2 parents c1930a4 + 4a48fb3 commit 233bd33
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 19 deletions.
2 changes: 1 addition & 1 deletion examples/tpm_test_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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 */
Expand Down
41 changes: 26 additions & 15 deletions src/tpm2_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -335,14 +335,22 @@ 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;
}

/* 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);
Expand All @@ -353,8 +361,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;
Expand All @@ -364,13 +372,10 @@ 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;

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;
}

Expand All @@ -388,6 +393,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;
Expand All @@ -410,14 +421,14 @@ 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;
return TPM_RC_SUCCESS;
}

int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key, byte *buffer,
Expand All @@ -436,8 +447,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)) {
Expand Down
97 changes: 97 additions & 0 deletions tests/unit_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
Expand Down
8 changes: 5 additions & 3 deletions wolftpm/tpm2_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 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)
\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
Expand Down

0 comments on commit 233bd33

Please sign in to comment.