From 21daf5a21cfcc2deae05908511dba3cf774044d5 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 26 Oct 2020 15:49:51 -0700 Subject: [PATCH] Key generation and loading examples using disk to store the key. Leverage wolfSSL filesystem abstraction. --- .gitignore | 5 ++ examples/README.md | 23 +++++ examples/include.am | 1 + examples/keygen/include.am | 23 +++++ examples/keygen/keygen.c | 152 ++++++++++++++++++++++++++++++++++ examples/keygen/keygen.h | 36 ++++++++ examples/keygen/keyload.c | 147 ++++++++++++++++++++++++++++++++ examples/pcr/quote_paramenc.c | 24 ++++-- src/tpm2_wrap.c | 53 ++++++++++-- wolftpm/tpm2_wrap.h | 12 +++ 10 files changed, 462 insertions(+), 14 deletions(-) create mode 100644 examples/keygen/include.am create mode 100644 examples/keygen/keygen.c create mode 100644 examples/keygen/keygen.h create mode 100644 examples/keygen/keyload.c diff --git a/.gitignore b/.gitignore index fad83ca..cc9c48d 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,8 @@ pkcs7tpmsignedex.p7s examples/tls/tls_server examples/tls/tls_client_notpm tests/unit.test +examples/keygen/keyload +examples/keygen/keygen # Generated Cert Files certs/ca-*.pem @@ -57,5 +59,8 @@ certs/*.par certs/crlnumber* certs/serial certs/index* + *.dep IDE/IAR-EWARM/settings +quote.blob +keyblob.bin diff --git a/examples/README.md b/examples/README.md index 40dd506..d2ac926 100644 --- a/examples/README.md +++ b/examples/README.md @@ -180,3 +180,26 @@ Note: This example can take an optional argument, the time value in miliseconds Performance benchmarks. `./examples/bench/bench` + +## Key Generation + +Examples for generating a TPM key blob and storing to disk, then loading from disk and loading into temporary TPM handle. + +``` +$ ./examples/keygen/keygen +TPM2.0 Key generation example +wolfTPM2_Init: success + +Loading SRK: Storage 0x81000200 (282 bytes) +Creating new RSA key... +Created new key (pub 280, priv 222 bytes) +Wrote 2168 bytes to keyblob.bin + +$ ./examples/keygen/keyload +TPM2.0 Key load example +wolfTPM2_Init: success + +Loading SRK: Storage 0x81000200 (282 bytes) +Reading 2168 bytes from keyblob.bin +Loaded key to 0x80000001 +``` diff --git a/examples/include.am b/examples/include.am index 24d2c19..37935d1 100644 --- a/examples/include.am +++ b/examples/include.am @@ -10,6 +10,7 @@ include examples/pkcs7/include.am include examples/timestamp/include.am include examples/pcr/include.am include examples/management/include.am +include examples/keygen/include.am dist_example_DATA+= examples/README.md \ examples/tpm_io.c \ diff --git a/examples/keygen/include.am b/examples/keygen/include.am new file mode 100644 index 0000000..6114cf8 --- /dev/null +++ b/examples/keygen/include.am @@ -0,0 +1,23 @@ +# vim:ft=automake +# All paths should be given relative to the root + +if BUILD_EXAMPLES +noinst_HEADERS += examples/keygen/keygen.h + +bin_PROGRAMS += examples/keygen/keyload +examples_keygen_keyload_SOURCES = examples/keygen/keyload.c \ + examples/tpm_io.c +examples_keygen_keyload_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_keygen_keyload_DEPENDENCIES = src/libwolftpm.la + +bin_PROGRAMS += examples/keygen/keygen +examples_keygen_keygen_SOURCES = examples/keygen/keygen.c \ + examples/tpm_io.c +examples_keygen_keygen_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_keygen_keygen_DEPENDENCIES = src/libwolftpm.la +endif + +dist_example_DATA+= examples/keygen/keyload.c +dist_example_DATA+= examples/keygen/keygen.c +DISTCLEANFILES+= examples/keygen/.libs/keyload +DISTCLEANFILES+= examples/keygen/.libs/keygen diff --git a/examples/keygen/keygen.c b/examples/keygen/keygen.c new file mode 100644 index 0000000..c113df7 --- /dev/null +++ b/examples/keygen/keygen.c @@ -0,0 +1,152 @@ +/* keygen.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Tool and example for creating, storing and loading keys using TPM2.0 */ + +#include + +#include +#include +#include + +#include + + +/******************************************************************************/ +/* --- BEGIN TPM Keygen Example -- */ +/******************************************************************************/ + +int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; /* SRK */ + WOLFTPM2_KEYBLOB newKey; + TPMT_PUBLIC publicTemplate; + TPMS_AUTH_COMMAND session[MAX_SESSION_NUM]; + TPMI_ALG_PUBLIC alg = TPM_ALG_RSA; /* TPM_ALG_ECC */ + +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + XFILE f; + const char* outputFile = "keyblob.bin"; + + if (argc >= 2) { + outputFile = argv[1]; + } +#endif + XMEMSET(session, 0, sizeof(session)); + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&newKey, 0, sizeof(newKey)); + + printf("TPM2.0 Key generation example\n"); + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + printf("wolfTPM2_Init: success\n\n"); + + + /* Define the default session auth that has NULL password */ + session[0].sessionHandle = TPM_RS_PW; + session[0].auth.size = 0; + TPM2_SetSessionAuth(session); + + /* See if SRK already exists */ + rc = wolfTPM2_ReadPublicKey(&dev, &storage, TPM2_DEMO_STORAGE_KEY_HANDLE); + if (rc != 0) { + printf("Loading SRK: Storage failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("Loading SRK: Storage 0x%x (%d bytes)\n", + (word32)storage.handle.hndl, storage.pub.size); + + /* set session for authorization of the storage key */ + session[0].auth.size = sizeof(gStorageKeyAuth)-1; + XMEMCPY(session[0].auth.buffer, gStorageKeyAuth, session[0].auth.size); + + /* Create new key */ + if (alg == TPM_ALG_RSA) { + rc = wolfTPM2_GetKeyTemplate_RSA_AIK(&publicTemplate); + } + else if (alg == TPM_ALG_ECC) { + rc = wolfTPM2_GetKeyTemplate_ECC_AIK(&publicTemplate); + } + else { + rc = BAD_FUNC_ARG; + goto exit; + } + printf("Creating new %s key...\n", TPM2_GetAlgName(alg)); + rc = wolfTPM2_CreateKey(&dev, &newKey, &storage.handle, + &publicTemplate, (const byte*)gAiKeyAuth, sizeof(gAiKeyAuth)-1); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateKey failed\n"); + goto exit; + } + printf("Created new key (pub %d, priv %d bytes)\n", + newKey.pub.size, newKey.priv.size); + + /* Save key as encrypted blob to the disk */ +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + f = XFOPEN(outputFile, "wb"); + if (f != XBADFILE) { + XFWRITE(&newKey.pub, 1, sizeof(newKey.pub), f); + XFWRITE(&newKey.priv, 1, sizeof(newKey.priv), f); + XFCLOSE(f); + } + printf("Wrote %d bytes to %s\n", + (int)sizeof(newKey.pub) + (int)sizeof(newKey.priv), outputFile); +#else + printf("Key Public Blob %d\n", newKey.pub.size); + TPM2_PrintBin(newKey.pub.publicArea, newKey.pub.size); + printf("Key Private Blob %d\n", newKey.priv.size); + TPM2_PrintBin(newKey.priv.buffer, newKey.priv.size); +#endif + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + /* Close key handles */ + wolfTPM2_UnloadHandle(&dev, &newKey.handle); + + wolfTPM2_Cleanup(&dev); + return rc; +} + +/******************************************************************************/ +/* --- END TPM Timestamp Test -- */ +/******************************************************************************/ + + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc; + + rc = TPM2_Keygen_Example(NULL, argc, argv); + + return rc; +} +#endif diff --git a/examples/keygen/keygen.h b/examples/keygen/keygen.h new file mode 100644 index 0000000..18811b5 --- /dev/null +++ b/examples/keygen/keygen.h @@ -0,0 +1,36 @@ +/* keygen.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _KEYGEN_H_ +#define _KEYGEN_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]); +int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _KEYGEN_H_ */ diff --git a/examples/keygen/keyload.c b/examples/keygen/keyload.c new file mode 100644 index 0000000..8e2eb9e --- /dev/null +++ b/examples/keygen/keyload.c @@ -0,0 +1,147 @@ +/* keyload.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Tool and example for creating, storing and loading keys using TPM2.0 */ + +#include + +#include +#include +#include + +#include + + +/******************************************************************************/ +/* --- BEGIN TPM Key Load Example -- */ +/******************************************************************************/ + +int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; /* SRK */ + WOLFTPM2_KEYBLOB newKey; + TPMS_AUTH_COMMAND session[MAX_SESSION_NUM]; +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + XFILE f; + const char* inputFile = "keyblob.bin"; + + if (argc >= 2) { + inputFile = argv[1]; + } +#endif + + XMEMSET(session, 0, sizeof(session)); + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&newKey, 0, sizeof(newKey)); + + printf("TPM2.0 Key load example\n"); + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + printf("wolfTPM2_Init: success\n\n"); + + + /* Define the default session auth that has NULL password */ + session[0].sessionHandle = TPM_RS_PW; + session[0].auth.size = 0; + TPM2_SetSessionAuth(session); + + /* See if SRK already exists */ + rc = wolfTPM2_ReadPublicKey(&dev, &storage, TPM2_DEMO_STORAGE_KEY_HANDLE); + if (rc != 0) { + printf("Loading SRK: Storage failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("Loading SRK: Storage 0x%x (%d bytes)\n", + (word32)storage.handle.hndl, storage.pub.size); + + /* set session for authorization of the storage key */ + session[0].auth.size = sizeof(gStorageKeyAuth)-1; + XMEMCPY(session[0].auth.buffer, gStorageKeyAuth, session[0].auth.size); + + /* Load encrypted key from the disk */ +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + f = XFOPEN(inputFile, "rb"); + if (f != XBADFILE) { + size_t fileSz; + XFSEEK(f, 0, XSEEK_END); + fileSz = XFTELL(f); + XREWIND(f); + if (fileSz > sizeof(newKey.priv) + sizeof(newKey.pub)) { + rc = BUFFER_E; + goto exit; + } + printf("Reading %d bytes from %s\n", (int)fileSz, inputFile); + + XFREAD(&newKey.pub, 1, sizeof(newKey.pub), f); + XFREAD(&newKey.priv, 1, sizeof(newKey.priv), f); + XFCLOSE(f); + } + else { + printf("File %s not found!\n", inputFile); + goto exit; + } +#else + /* TODO: Option to load hex blob */ + printf("Loading blob from disk not supported\n") +#endif + + rc = wolfTPM2_LoadKey(&dev, &newKey, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadKey failed\n"); + goto exit; + } + printf("Loaded key to 0x%x\n", + (word32)newKey.handle.hndl); + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + /* Close key handles */ + wolfTPM2_UnloadHandle(&dev, &newKey.handle); + + wolfTPM2_Cleanup(&dev); + return rc; +} + +/******************************************************************************/ +/* --- END TPM Timestamp Test -- */ +/******************************************************************************/ + + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc; + + rc = TPM2_Keyload_Example(NULL, argc, argv); + + return rc; +} +#endif diff --git a/examples/pcr/quote_paramenc.c b/examples/pcr/quote_paramenc.c index 7a27c44..e5dbf10 100644 --- a/examples/pcr/quote_paramenc.c +++ b/examples/pcr/quote_paramenc.c @@ -32,8 +32,8 @@ #include #include /* atoi */ -const char defaultFilename[] = "quote.blob\0"; -const char userData[] = "ThisIsData"; +static const char defaultFilename[] = "quote.blob"; +static const char userData[] = "ThisIsData"; /******************************************************************************/ /* --- BEGIN TPM2.0 Quote Test with Parameter Encryption over user data --- */ @@ -55,7 +55,9 @@ int TPM2_Quote_Test(void* userCtx, int argc, char *argv[]) int pcrIndex, rc = -1; const char *filename = NULL; BYTE *data = NULL; - FILE *quoteBlob = NULL; +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + XFILE quoteBlob = NULL; +#endif WOLFTPM2_DEV dev; TPMS_ATTEST attestedData; @@ -102,12 +104,14 @@ int TPM2_Quote_Test(void* userCtx, int argc, char *argv[]) goto exit_badargs; } - quoteBlob = fopen(filename, "wb"); - if (quoteBlob == NULL) { +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + quoteBlob = XFOPEN(filename, "wb"); + if (quoteBlob == XBADFILE) { printf("Error opening file %s\n", filename); usage(); goto exit_badargs; } +#endif printf("Demo of TPM2.0 Quote with parameter encryption over user data\n"); rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); @@ -240,13 +244,15 @@ int TPM2_Quote_Test(void* userCtx, int argc, char *argv[]) attestedData.magic); } - if(quoteBlob) { +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + if (quoteBlob != XBADFILE) { data = (UINT8*)&cmdOut.quoteResult.quoted; data += 2; /* skip the size field of TPMS_ATTEST */ - if(fwrite(data, sizeof(TPMS_ATTEST)-2, 1, quoteBlob) != 1) { + if (XFWRITE(data, 1, sizeof(TPMS_ATTEST)-2, quoteBlob) != sizeof(TPMS_ATTEST)-2) { printf("Error while writing to a %s file\n", filename); } } +#endif printf("TPM with signature attests (type 0x%x):\n", attestedData.type); printf("\tTPM signed %lu count of PCRs\n", @@ -276,9 +282,11 @@ exit: exit_badargs: +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) if (quoteBlob != NULL) { - fclose(quoteBlob); + XFCLOSE(quoteBlob); } +#endif return rc; } diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 4deec8d..1027037 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -609,21 +609,19 @@ int wolfTPM2_ChangeAuthKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } -int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, +int wolfTPM2_CreateKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* key, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate, const byte* auth, int authSz) { int rc; Create_In createIn; Create_Out createOut; - Load_In loadIn; - Load_Out loadOut; if (dev == NULL || key == NULL || parent == NULL || publicTemplate == NULL) return BAD_FUNC_ARG; /* clear output key buffer */ - XMEMSET(key, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(key, 0, sizeof(*key)); /* set session auth for key */ dev->session[0].auth = parent->auth; @@ -656,12 +654,35 @@ int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, printf("TPM2_Create key: pub %d, priv %d\n", createOut.outPublic.size, createOut.outPrivate.size); #endif + + key->handle.dev = dev; + key->handle.auth = createIn.inSensitive.sensitive.userAuth; key->pub = createOut.outPublic; + key->priv = createOut.outPrivate; + + /* clear auth */ + XMEMSET(&dev->session[0].auth, 0, sizeof(dev->session[0].auth)); + + return rc; +} + +int wolfTPM2_LoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* key, + WOLFTPM2_HANDLE* parent) +{ + int rc; + Load_In loadIn; + Load_Out loadOut; + + if (dev == NULL || key == NULL || parent == NULL) + return BAD_FUNC_ARG; + + /* set session auth for key */ + dev->session[0].auth = parent->auth; /* Load new key */ XMEMSET(&loadIn, 0, sizeof(loadIn)); loadIn.parentHandle = parent->hndl; - loadIn.inPrivate = createOut.outPrivate; + loadIn.inPrivate = key->priv; loadIn.inPublic = key->pub; rc = TPM2_Load(&loadIn, &loadOut); if (rc != TPM_RC_SUCCESS) { @@ -673,7 +694,6 @@ int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, } key->handle.dev = dev; key->handle.hndl = loadOut.objectHandle; - key->handle.auth = createIn.inSensitive.sensitive.userAuth; #ifdef DEBUG_WOLFTPM printf("TPM2_Load Key Handle 0x%x\n", (word32)key->handle.hndl); @@ -685,6 +705,27 @@ int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, + WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate, + const byte* auth, int authSz) +{ + int rc; + WOLFTPM2_KEYBLOB keyBlob; + + if (dev == NULL || key == NULL) + return BAD_FUNC_ARG; + + rc = wolfTPM2_CreateKey(dev, &keyBlob, parent, publicTemplate, auth, authSz); + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_LoadKey(dev, &keyBlob, parent); + } + + /* return new key */ + XMEMCPY(key, &keyBlob, sizeof(WOLFTPM2_KEY)); + + return rc; +} + int wolfTPM2_LoadPublicKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const TPM2B_PUBLIC* pub) { diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index ca50699..78848fa 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -50,6 +50,13 @@ typedef struct WOLFTPM2_KEY { TPM2B_NAME name; } WOLFTPM2_KEY; +typedef struct WOLFTPM2_KEYBLOB { + WOLFTPM2_HANDLE handle; + TPM2B_PUBLIC pub; + TPM2B_NAME name; + TPM2B_PRIVATE priv; +} WOLFTPM2_KEYBLOB; + typedef struct WOLFTPM2_HASH { WOLFTPM2_HANDLE handle; } WOLFTPM2_HASH; @@ -130,6 +137,11 @@ WOLFTPM_API int wolfTPM2_CreatePrimaryKey(WOLFTPM2_DEV* dev, const byte* auth, int authSz); WOLFTPM_API int wolfTPM2_ChangeAuthKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, WOLFTPM2_HANDLE* parent, const byte* auth, int authSz); +WOLFTPM_API int wolfTPM2_CreateKey(WOLFTPM2_DEV* dev, + WOLFTPM2_KEYBLOB* key, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate, + const byte* auth, int authSz); +WOLFTPM_API int wolfTPM2_LoadKey(WOLFTPM2_DEV* dev, + WOLFTPM2_KEYBLOB* key, WOLFTPM2_HANDLE* parent); WOLFTPM_API int wolfTPM2_CreateAndLoadKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate, const byte* auth, int authSz);