From df13479ac77618d7a3f906bf7046631690e1bcbb Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Tue, 9 Feb 2021 22:19:50 +0200 Subject: [PATCH 1/8] Added new examples for storing TPM keys in NVRAM, with parameter encryption * Added examples/nvram/store for storing TPM key in NVRAM * Added examples/nvram/read for extracting keys from the TPM's NVRAM Signed-off-by: Dimitar Tomov --- examples/include.am | 1 + examples/nvram/include.am | 26 ++++++ examples/nvram/read.c | 178 ++++++++++++++++++++++++++++++++++++++ examples/nvram/store.c | 170 ++++++++++++++++++++++++++++++++++++ examples/nvram/store.h | 36 ++++++++ examples/tpm_test.h | 3 +- 6 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 examples/nvram/include.am create mode 100644 examples/nvram/read.c create mode 100644 examples/nvram/store.c create mode 100644 examples/nvram/store.h diff --git a/examples/include.am b/examples/include.am index eab540d..edadd6f 100644 --- a/examples/include.am +++ b/examples/include.am @@ -11,6 +11,7 @@ include examples/timestamp/include.am include examples/pcr/include.am include examples/management/include.am include examples/keygen/include.am +include examples/nvram/include.am dist_example_DATA+= examples/README.md \ examples/tpm_io.c \ diff --git a/examples/nvram/include.am b/examples/nvram/include.am new file mode 100644 index 0000000..cf401c1 --- /dev/null +++ b/examples/nvram/include.am @@ -0,0 +1,26 @@ +# vim:ft=automake +# All paths should be given relative to the root + +if BUILD_EXAMPLES +noinst_HEADERS += examples/nvram/store.h + +bin_PROGRAMS += examples/nvram/store +examples_nvram_store_SOURCES = examples/nvram/store.c \ + examples/tpm_test_keys.c \ + examples/tpm_io.c +examples_nvram_store_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_store_DEPENDENCIES = src/libwolftpm.la + +bin_PROGRAMS += examples/nvram/read +examples_nvram_read_SOURCES = examples/nvram/read.c \ + examples/tpm_test_keys.c \ + examples/tpm_io.c +examples_nvram_read_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_read_DEPENDENCIES = src/libwolftpm.la + +endif + +dist_example_DATA+= examples/nvram/store.c +dist_example_DATA+= examples/nvram/read.c +DISTCLEANFILES+= examples/nvram/.libs/store +DISTCLEANFILES+= examples/nvram/.libs/read diff --git a/examples/nvram/read.c b/examples/nvram/read.c new file mode 100644 index 0000000..5a23365 --- /dev/null +++ b/examples/nvram/read.c @@ -0,0 +1,178 @@ +/* read.c + * + * Copyright (C) 2006-2021 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 extracting a TPM key from the TPM's NVRAM + * + * NB: This example uses Parameter Encryption to protect + * the Password Authorization of the TPM NVRAM Index + * + **/ + +#include + +#include +#include +#include +#include + +#include +#include + +#ifndef WOLFTPM2_NO_WRAPPER + +#define ARGC_PUB_SIZE 1 +#define ARGC_PRIV_SIZE 2 +#define ARGC_PARAM_ENC 3 + +/******************************************************************************/ +/* --- BEGIN TPM Keygen Example -- */ +/******************************************************************************/ +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/read priv pub [-aes/-xor]\n"); + printf("* priv: size in bytes of the private part of the key in NV\n"); + printf("* pub: size in bytes of the public part of the key in NV\n"); + printf("* -aes/xor: Use Parameter Encryption\n"); +} + +int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_KEYBLOB keyBlob; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_HANDLE parent; + WOLFTPM2_NV nv; + TPM2B_AUTH auth; + word32 readSize; + int paramEncAlg = TPM_ALG_NULL; + + if (argc > 2) { + XMEMSET(&keyBlob, 0, sizeof(keyBlob)); + keyBlob.pub.size = atoi(argv[ARGC_PUB_SIZE]); + keyBlob.priv.size = atoi(argv[ARGC_PRIV_SIZE]); + + if (argc == 4) { + if (XSTRNCMP(argv[ARGC_PARAM_ENC], "-aes", 4) == 0) { + paramEncAlg = TPM_ALG_CFB; + } + if (XSTRNCMP(argv[ARGC_PARAM_ENC], "-xor", 4) == 0) { + paramEncAlg = TPM_ALG_XOR; + } + argc--; + } + } + else { + usage(); + return 0; + } + + if (keyBlob.priv.size == 0 || keyBlob.pub.size == 0) { + printf("Specify size of private and public part of the key\n"); + usage(); + return 0; + } + + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&parent, 0, sizeof(parent)); + XMEMSET(&auth, 0, sizeof(auth)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + + if (paramEncAlg != TPM_ALG_NULL) { + /* Start TPM session for parameter encryption */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_HMAC, TPM_ALG_CFB); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + /* Set TPM session attributes for parameter encryption */ + rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + } + + auth.size = sizeof(gNvAuth)-1; + XMEMCPY(auth.buffer, gNvAuth, auth.size); + + /* Prepare auth for NV Index */ + XMEMSET(&nv, 0, sizeof(nv)); + nv.handle.hndl = TPM2_DEMO_NVRAM_STORE_PRIV_INDEX; + nv.handle.auth.size = auth.size; + XMEMCPY(nv.handle.auth.buffer, auth.buffer, auth.size); + + readSize = keyBlob.pub.size; + printf("Trying to read %d bytes of public key part from NV\n", readSize); + rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + (byte*)&keyBlob.pub.publicArea, &readSize, 0); + if (rc != 0) goto exit; + + readSize = keyBlob.priv.size; + printf("Trying to read %d bytes of private key part from NV\n", readSize); + rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + (byte*)&keyBlob.priv.buffer, &readSize, keyBlob.pub.size); + if (rc != 0) goto exit; + + parent.hndl = TPM_RH_OWNER; + rc = wolfTPM2_NVDeleteAuth(&dev, &parent, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + if (rc != 0) goto exit; + + printf("Extraction of key from NVRAM at index 0x%x succeeded\n" , + TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM NVRAM Store Example -- */ +/******************************************************************************/ +#endif /* !WOLFTPM2_NO_WRAPPER */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = NOT_COMPILED_IN; + +#ifndef WOLFTPM2_NO_WRAPPER + rc = TPM2_NVRAM_Read_Example(NULL, argc, argv); +#else + printf("NVRAM code not compiled in\n"); + (void)argc; + (void)argv; +#endif + + return rc; +} +#endif diff --git a/examples/nvram/store.c b/examples/nvram/store.c new file mode 100644 index 0000000..f61d4b0 --- /dev/null +++ b/examples/nvram/store.c @@ -0,0 +1,170 @@ +/* store.c + * + * Copyright (C) 2006-2021 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 storing a TPM key into the TPM's NVRAM + * + * NB: This example uses Parameter Encryption to protect the password of the + * TPM NVRAM Index, where the private and public parts of a TPM key is stored + * + **/ + +#include + +#include +#include +#include +#include + +#include + +#ifndef WOLFTPM2_NO_WRAPPER + +/******************************************************************************/ +/* --- BEGIN TPM Keygen Example -- */ +/******************************************************************************/ +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/store [filename] [-aes/-xor]\n"); + printf("* filename: point to a file containing a TPM key\n"); + printf("\tIf not supplied, default filename is \"keyblob.bin\"\n"); + printf("* -aes/xor: Use Parameter Encryption\n"); +} + +int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_KEYBLOB keyBlob; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_HANDLE parent; + WOLFTPM2_NV nv; + TPM2B_AUTH auth; + word32 nvAttributes; + const char* filename = "keyblob.bin"; + int paramEncAlg = TPM_ALG_NULL; + + if (argc >= 2) { + if (XSTRNCMP(argv[1], "-?", 2) == 0 || + XSTRNCMP(argv[1], "-h", 2) == 0 || + XSTRNCMP(argv[1], "--help", 6) == 0) { + usage(); + return 0; + } + if (argv[1][0] != '-') { + filename = argv[1]; + } + } + while (argc > 1) { + if (XSTRNCMP(argv[argc-1], "-aes", 4) == 0) { + paramEncAlg = TPM_ALG_CFB; + } + if (XSTRNCMP(argv[argc-1], "-xor", 4) == 0) { + paramEncAlg = TPM_ALG_XOR; + } + argc--; + }; + + XMEMSET(&keyBlob, 0, sizeof(keyBlob)); + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&parent, 0, sizeof(parent)); + XMEMSET(&auth, 0, sizeof(auth)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + + if (paramEncAlg != TPM_ALG_NULL) { + /* Start TPM session for parameter encryption */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_HMAC, TPM_ALG_CFB); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + /* Set TPM session attributes for parameter encryption */ + rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + } + + rc = readKeyBlob(filename, &keyBlob); + if (rc != 0) goto exit; + + /* Prepare NV_AUTHWRITE and NV_AUTHREAD attributes necessary for password */ + parent.hndl = TPM_RH_OWNER; + rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes); + if (rc != 0) goto exit; + + /* Our wolfTPM2 wrapper for NV_Define */ + rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + nvAttributes, TPM2_DEMO_NV_TEST_SIZE, (byte*)gNvAuth, sizeof(gNvAuth)-1); + if (rc != 0 && rc != TPM_RC_NV_DEFINED) goto exit; + + printf("Storing key at TPM NV index 0x%x with password protection\n", + TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + + printf("Public part = %d bytes\n", keyBlob.pub.size); + rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + (byte*)&keyBlob.pub.publicArea, keyBlob.pub.size, 0); + if (rc != 0) goto exit; + + printf("Private part = %d bytes\n", keyBlob.priv.size); + rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + keyBlob.priv.buffer, keyBlob.priv.size, keyBlob.pub.size); + if (rc != 0) goto exit; + + printf("NV write succeeded\n"); + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM NVRAM Store Example -- */ +/******************************************************************************/ +#endif /* !WOLFTPM2_NO_WRAPPER */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = NOT_COMPILED_IN; + +#ifndef WOLFTPM2_NO_WRAPPER + rc = TPM2_NVRAM_Store_Example(NULL, argc, argv); +#else + printf("NVRAM code not compiled in\n"); + (void)argc; + (void)argv; +#endif + + return rc; +} +#endif diff --git a/examples/nvram/store.h b/examples/nvram/store.h new file mode 100644 index 0000000..85a3121 --- /dev/null +++ b/examples/nvram/store.h @@ -0,0 +1,36 @@ +/* store.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 _STORE_H_ +#define _STORE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]); +int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _Store_H_ */ diff --git a/examples/tpm_test.h b/examples/tpm_test.h index f6686af..a9888dd 100755 --- a/examples/tpm_test.h +++ b/examples/tpm_test.h @@ -32,7 +32,6 @@ /* Test Configuration */ #define TPM2_DEMO_STORAGE_KEY_HANDLE 0x81000200 /* Persistent Storage Key Handle (RSA) */ #define TPM2_DEMO_STORAGE_EC_KEY_HANDLE 0x81000201 /* Persistent Storage Key Handle (ECC) */ - #define TPM2_DEMO_RSA_IDX 0x20 /* offset handle to unused index */ #define TPM2_DEMO_RSA_KEY_HANDLE (0x81000000 + TPM2_DEMO_RSA_IDX) /* Persistent Key Handle */ #define TPM2_DEMO_RSA_CERT_HANDLE (0x01800000 + TPM2_DEMO_RSA_IDX) /* NV Handle */ @@ -43,6 +42,8 @@ #define TPM2_DEMO_NV_TEST_INDEX 0x01800200 #define TPM2_DEMO_NV_TEST_AUTH_INDEX 0x01800201 +#define TPM2_DEMO_NVRAM_STORE_PUB_INDEX 0x01800202 +#define TPM2_DEMO_NVRAM_STORE_PRIV_INDEX 0x01800203 #define TPM2_DEMO_NV_TEST_SIZE 1024 /* max size on Infineon SLB9670 is 1664 */ static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth"; From 33861a676a4a29e82c2187f688c6f07ea322de86 Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Fri, 12 Feb 2021 13:24:00 +0200 Subject: [PATCH 2/8] Update NVRAM attributes information Signed-off-by: Dimitar Tomov --- src/tpm2_wrap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index af20660..493f0a5 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -3768,9 +3768,11 @@ int wolfTPM2_GetNvAttributesTemplate(TPM_HANDLE auth, word32* nvAttributes) return BAD_FUNC_ARG; *nvAttributes = ( - TPMA_NV_AUTHWRITE | TPMA_NV_OWNERWRITE | /* write allowed */ - TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD | /* read allowed */ - TPMA_NV_NO_DA /* no dictionary attack */ + TPMA_NV_AUTHWRITE | /* password or HMAC can authorize writing */ + TPMA_NV_AUTHREAD | /* password or HMAC can authorize reading */ + TPMA_NV_OWNERWRITE | /* Owner Hierarchy auth can be used also */ + TPMA_NV_OWNERREAD | /* Owner Hierarchy auth for read */ + TPMA_NV_NO_DA /* Don't increment dictionary attack counter */ ); if (auth == TPM_RH_PLATFORM) { From df0107605ea9ec60856be2e33ad80b7b1fb1138e Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Thu, 18 Feb 2021 00:13:14 +0200 Subject: [PATCH 3/8] Added TPM2_PrintAuth for debugging purposes Signed-off-by: Dimitar Tomov --- src/tpm2.c | 17 ++++++++++++++++- src/tpm2_packet.c | 2 ++ wolftpm/tpm2.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/tpm2.c b/src/tpm2.c index 27fe2a1..13c392b 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -4609,9 +4609,10 @@ TPM_RC TPM2_NV_DefineSpace(NV_DefineSpace_In* in) TPM2_Packet_AppendU32(&packet, in->authHandle); info.authCnt = TPM2_Packet_AppendAuth(&packet, ctx); + /* 1st TPM2B parameter, TPM2B_AUTH different from Authorization Area */ TPM2_Packet_AppendU16(&packet, in->auth.size); TPM2_Packet_AppendBytes(&packet, in->auth.buffer, in->auth.size); - + /* 2nd TPM2B parameter, TPM2B_PUBLIC */ in->publicInfo.size = 4 + 2 + 4 + 2 + in->publicInfo.nvPublic.authPolicy.size + 2; TPM2_Packet_AppendU16(&packet, in->publicInfo.size); @@ -5686,6 +5687,20 @@ void TPM2_PrintBin(const byte* buffer, word32 length) length -= sz; } } + +void TPM2_PrintAuth(const TPMS_AUTH_COMMAND* authCmd) +{ + if (authCmd == NULL) + return; + + printf("authCmd:\n"); + printf("sessionHandle=0x%7X\n", authCmd->sessionHandle); + printf("nonceSize=%u nonceBuffer:\n", authCmd->nonce.size); + TPM2_PrintBin(authCmd->nonce.buffer, authCmd->nonce.size); + printf("sessionAttributes=0x%2X\n", authCmd->sessionAttributes); + printf("hmacSize=%u hmacBuffer:\n", authCmd->hmac.size); + TPM2_PrintBin(authCmd->hmac.buffer, authCmd->hmac.size); +} #endif /******************************************************************************/ diff --git a/src/tpm2_packet.c b/src/tpm2_packet.c index a8293c2..03c2936 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -320,6 +320,8 @@ void TPM2_Packet_AppendAuthCmd(TPM2_Packet* packet, TPMS_AUTH_COMMAND* authCmd) if (packet == NULL || authCmd == NULL) return; + TPM2_PrintAuth(authCmd); + /* make sure continueSession is set for TPM_RS_PW */ if (authCmd->sessionHandle == TPM_RS_PW && (authCmd->sessionAttributes & TPMA_SESSION_continueSession) == 0) { diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 34dad54..57dc4c8 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -2819,8 +2819,10 @@ WOLFTPM_API UINT16 TPM2_GetVendorID(void); #ifdef DEBUG_WOLFTPM WOLFTPM_API void TPM2_PrintBin(const byte* buffer, word32 length); +WOLFTPM_API void TPM2_PrintAuth(const TPMS_AUTH_COMMAND* authCmd); #else #define TPM2_PrintBin(b, l) +#define TPM2_PrintAuth(b, l) #endif #ifdef __cplusplus From 87e29005bf466931053936b1b051ce15d591986e Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Thu, 18 Feb 2021 19:06:10 +0200 Subject: [PATCH 4/8] Fix parameter encryption for NVRAM commands * Make sure hmac buffer space is reserved * Add name computation for NV handles, modify TPM2_GetName * Make TPM2_GetName handle multiple TPM Handle types * Add wolfTPM2_SetNameHandle for passing handle name to parameter encryption * Compute fresh NV Index Name during NVWrite with updated nvPublic information * Compute fresh NV Index Name during NVRead, the same way NVWrite needs it The NV_WRITTEN flag is being set, when there are consequtive reads, which forces the hash to update. In order for this to take place, we need to read the current(fresh) nvPublic information using TPM2_NV_ReadPublic. * Add wolfTPM2_UnsetAuth to clear past authorization sessions when not needed A way to clear auth sessions that are no longer needed was missing. For example, after a TPM2_NVRead which uses two auth session slots, there was no way for the user to clear the second slot afterwards. The only possibility before was to overwrite with invalid values. This way a TPM2_NVUndefineSpace would fail right after TPM2_NVRead, just because there was an auth session not prevously cleared. This can be handled either by the user manually or the user can use wolfTPM2 wrappers that handle it now automatically using wolfTPM2_UnsetAuth. Signed-off-by: Dimitar Tomov --- src/tpm2.c | 97 +++++++++++++++++++++++++++++++++++++--- src/tpm2_packet.c | 2 + src/tpm2_wrap.c | 106 +++++++++++++++++++++++++++++++++++++++++++- wolftpm/tpm2.h | 3 +- wolftpm/tpm2_wrap.h | 2 + 5 files changed, 203 insertions(+), 7 deletions(-) diff --git a/src/tpm2.c b/src/tpm2.c index 13c392b..9b7218d 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -108,7 +108,8 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, int rc = TPM_RC_SUCCESS; UINT32 authSz; BYTE *param, *encParam = NULL; - int paramSz, encParamSz = 0, authPos, i; + int paramSz, encParamSz = 0; + int i, authPos, handlePos; /* Skip the header and handles area */ packet->pos = TPM2_HEADER_SIZE + (info->inHandleCnt * sizeof(TPM_HANDLE)); @@ -187,9 +188,16 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, } #ifndef WOLFTPM2_NO_WOLFCRYPT - rc = TPM2_GetName(ctx, info->inHandleCnt, 0, &name1); - rc |= TPM2_GetName(ctx, info->inHandleCnt, 1, &name2); - rc |= TPM2_GetName(ctx, info->inHandleCnt, 2, &name3); + UINT32 handleValue; + + handlePos = packet->pos; + packet->pos = TPM2_HEADER_SIZE; /* Handles are right after header */ + TPM2_Packet_ParseU32(packet, &handleValue); + packet->pos = handlePos; + + rc = TPM2_GetName(ctx, handleValue, info->inHandleCnt, 0, &name1); + rc |= TPM2_GetName(ctx, handleValue, info->inHandleCnt, 1, &name2); + rc |= TPM2_GetName(ctx, handleValue, info->inHandleCnt, 2, &name3); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM printf("Error getting names for cpHash!\n"); @@ -5269,7 +5277,7 @@ int TPM2_GetNonce(byte* nonceBuf, int nonceSz) } /* Get name for object/handle */ -int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name) +int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name) { TPM2_AUTH_SESSION* session; @@ -5279,10 +5287,28 @@ int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name) return TPM_RC_SUCCESS; session = &ctx->session[idx]; + +#if 0 if (session->name.size > 0) { name->size = session->name.size; XMEMCPY(name->name, session->name.name, name->size); } + (void)handleValue; +#else + if ((handleValue >= TRANSIENT_FIRST) || + (handleValue >= NV_INDEX_FIRST && handleValue <= NV_INDEX_LAST)) { + if (session->name.size > 0) { + name->size = session->name.size; + XMEMCPY(name->name, session->name.name, name->size); + } + } + else { + handleValue = TPM2_Packet_SwapU32(handleValue); + name->size = sizeof(handleValue); + XMEMCPY(name->name, (byte*)&handleValue, name->size); + } +#endif + #ifdef WOLFTPM_DEBUG_VERBOSE printf("Name %d: %d\n", idx, name->size); TPM2_PrintBin(name->name, name->size); @@ -5649,6 +5675,67 @@ UINT16 TPM2_GetVendorID(void) return vid; } +/* Stores nameAlg + the digest of nvPublic in buffer, total size in size */ +int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) +{ + int rc; +#ifndef WOLFTPM2_NO_WOLFCRYPT + int hashSize, nameAlgValue, nameAlgSize; + wc_HashAlg hash; + enum wc_HashType hashType; + byte appending[sizeof(TPMS_NV_PUBLIC)]; + TPM2B_DIGEST digest; + TPM2_Packet packet; + + /* Prepare temporary buffer */ + packet.buf = appending; + packet.pos = 0; + packet.size = sizeof(appending); + + /* nvPublic must be in Marshaled state for hashing */ + TPM2_Packet_AppendU32(&packet, nvPublic->nvIndex); + TPM2_Packet_AppendU16(&packet, nvPublic->nameAlg); + TPM2_Packet_AppendU32(&packet, nvPublic->attributes); + TPM2_Packet_AppendU16(&packet, nvPublic->authPolicy.size); + TPM2_Packet_AppendBytes(&packet, nvPublic->authPolicy.buffer, + nvPublic->authPolicy.size); + TPM2_Packet_AppendU16(&packet, nvPublic->dataSize); + + /* Hashing nvPublic */ + rc = TPM2_GetHashType(nvPublic->nameAlg); + hashType = (enum wc_HashType)rc; + rc = wc_HashGetDigestSize(hashType); + if (rc < 0) { + return rc; + } + hashSize = rc; + + rc = wc_HashInit(&hash, hashType); + if(rc == 0) { + rc = wc_HashUpdate(&hash, hashType, packet.buf, packet.pos); + } + + if (rc == 0) { + rc = wc_HashFinal(&hash, hashType, digest.buffer); + } + + if (rc == 0) { + nameAlgValue = TPM2_Packet_SwapU16(nvPublic->nameAlg); + nameAlgSize = sizeof(nvPublic->nameAlg); + XMEMCPY(buffer, (byte*)&nameAlgValue, nameAlgSize); + XMEMCPY(&buffer[2], digest.buffer, hashSize); + /* account for nameAlg concatenation */ + *size = hashSize + nameAlgSize; + } + + wc_HashFree(&hash, hashType); + + return TPM_RC_SUCCESS; +#else + return TPM_RC_FAILURE; +#endif +} + #ifdef DEBUG_WOLFTPM #define LINE_LEN 16 void TPM2_PrintBin(const byte* buffer, word32 length) diff --git a/src/tpm2_packet.c b/src/tpm2_packet.c index 03c2936..1260f52 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -320,7 +320,9 @@ void TPM2_Packet_AppendAuthCmd(TPM2_Packet* packet, TPMS_AUTH_COMMAND* authCmd) if (packet == NULL || authCmd == NULL) return; +#ifdef WOLFTPM_DEBUG_VERBOSE TPM2_PrintAuth(authCmd); +#endif /* make sure continueSession is set for TPM_RS_PW */ if (authCmd->sessionHandle == TPM_RS_PW && diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 493f0a5..e21df7e 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -26,6 +26,11 @@ /* For some struct to buffer conversions */ #include +#ifndef WOLFTPM2_NO_WOLFCRYPT +/* Required in wolfTPM2_CreateAuth() for name computation of NV handles */ +#include +#endif + /* Local Functions */ static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap); @@ -369,6 +374,20 @@ int wolfTPM2_GetCapabilities(WOLFTPM2_DEV* dev, WOLFTPM2_CAPS* cap) return wolfTPM2_GetCapabilities_NoDev(cap); } +int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index) +{ + TPM2_AUTH_SESSION* session; + + if (dev == NULL || index >= MAX_SESSION_NUM) { + return BAD_FUNC_ARG; + } + + session = &dev->session[index]; + XMEMSET(session, 0, sizeof(TPM2_AUTH_SESSION)); + + return TPM2_SetSessionAuth(dev->session); +} + int wolfTPM2_SetAuth(WOLFTPM2_DEV* dev, int index, TPM_HANDLE sessionHandle, const TPM2B_AUTH* auth, TPMA_SESSION sessionAttributes, const TPM2B_NAME* name) @@ -415,6 +434,24 @@ int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, return wolfTPM2_SetAuth(dev, index, TPM_RS_PW, auth, 0, name); } +int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index, + const WOLFTPM2_HANDLE* handle) +{ + const TPM2B_NAME* name = NULL; + TPM2_AUTH_SESSION* session; + + if (dev == NULL || handle == NULL || index >= MAX_SESSION_NUM) { + return BAD_FUNC_ARG; + } + + name = &handle->name; + session = &dev->session[index]; + + session->name.size = name->size; + XMEMCPY(session->name.name, name->name, session->name.size); + return TPM_RC_SUCCESS; +} + int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes) { @@ -446,6 +483,15 @@ int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index, session->nonceTPM.size = tpmSession->nonceTPM.size; XMEMCPY(session->nonceTPM.buffer, tpmSession->nonceTPM.buffer, session->nonceTPM.size); + + /* Parameter Encryption session will have an hmac added later. + * Reserve space, the same way it was done for nonceCaller above. + */ + if (session->sessionHandle != TPM_RS_PW && + ((session->sessionAttributes & TPMA_SESSION_encrypt) || + (session->sessionAttributes & TPMA_SESSION_decrypt))) { + session->auth.size = TPM2_GetHashDigestSize(session->authHash); + } } return rc; } @@ -2524,6 +2570,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, { int rc; NV_DefineSpace_In in; + TPM2B_NAME name; if (dev == NULL || nv == NULL) return BAD_FUNC_ARG; @@ -2533,6 +2580,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, wolfTPM2_SetAuthHandle(dev, 0, parent); } + XMEMSET(&name, 0, sizeof(name)); XMEMSET(&in, 0, sizeof(in)); in.authHandle = parent->hndl; if (auth && authSz > 0) { @@ -2560,9 +2608,15 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, return rc; } + /* Compute NV Index name in case of parameter encryption */ + rc = TPM2_HashNvPublic(&in.publicInfo.nvPublic, name.name, &name.size); + /* return new NV handle */ + XMEMSET(nv, 0, sizeof(*nv)); nv->handle.hndl = (TPM_HANDLE)nvIndex; nv->handle.auth = in.auth; + nv->handle.name.size = name.size; + XMEMCPY(&nv->handle.name.name, name.name, nv->handle.name.size); #ifdef DEBUG_WOLFTPM printf("TPM2_NV_DefineSpace: Auth 0x%x, Idx 0x%x, Attribs 0x%d, Size %d\n", @@ -2596,6 +2650,8 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, int rc = TPM_RC_SUCCESS; word32 pos = 0, towrite; NV_Write_In in; + NV_ReadPublic_In inPublic; + NV_ReadPublic_Out outPublic; if (dev == NULL || nv == NULL) return BAD_FUNC_ARG; @@ -2605,6 +2661,27 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } + XMEMSET((byte*)&inPublic, 0, sizeof(inPublic)); + XMEMSET((byte*)&outPublic, 0, sizeof(outPublic)); + /* Read the NV Index publicArea to have up to date NV Index Name */ + inPublic.nvIndex = nv->handle.hndl; + rc = TPM2_NV_ReadPublic(&inPublic, &outPublic); + if (rc != TPM_RC_SUCCESS) { + #ifdef DEBUG_WOLFTPM + printf("Failed to read fresh NvPublic\n"); + #endif + return TPM_RC_FAILURE; + } + + /* Compute NV Index name in case of parameter encryption */ + rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic, + (byte*)&nv->handle.name.name, + &nv->handle.name.size); + + /* Necessary, because NVWrite has two handles, second is NV Index */ + wolfTPM2_SetNameHandle(dev, 0, &nv->handle); + wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + while (dataSz > 0) { towrite = dataSz; if (towrite > MAX_NV_BUFFER_SIZE) @@ -2629,7 +2706,8 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, #ifdef DEBUG_WOLFTPM printf("TPM2_NV_Write: Auth 0x%x, Idx 0x%x, Offset %d, Size %d\n", - (word32)in.authHandle, (word32)in.nvIndex, in.offset, in.data.size); + (word32)in.authHandle, (word32)in.nvIndex, + in.offset, in.data.size); #endif pos += towrite; @@ -2656,6 +2734,8 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 pos = 0, toread, dataSz; NV_Read_In in; NV_Read_Out out; + NV_ReadPublic_In inPublic; + NV_ReadPublic_Out outPublic; if (dev == NULL || nv == NULL || pDataSz == NULL) return BAD_FUNC_ARG; @@ -2665,6 +2745,27 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } + XMEMSET((byte*)&inPublic, 0, sizeof(inPublic)); + XMEMSET((byte*)&outPublic, 0, sizeof(outPublic)); + /* Read the NV Index publicArea to have up to date NV Index Name */ + inPublic.nvIndex = nv->handle.hndl; + rc = TPM2_NV_ReadPublic(&inPublic, &outPublic); + if (rc != TPM_RC_SUCCESS) { + #ifdef DEBUG_WOLFTPM + printf("Failed to read fresh NvPublic\n"); + #endif + return TPM_RC_FAILURE; + } + + /* Compute NV Index name in case of parameter encryption */ + rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic, + (byte*)&nv->handle.name.name, + &nv->handle.name.size); + + /* Necessary, because NVWrite has two handles, second is NV Index */ + wolfTPM2_SetNameHandle(dev, 0, &nv->handle); + wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + dataSz = *pDataSz; while (dataSz > 0) { @@ -2773,6 +2874,9 @@ int wolfTPM2_NVDeleteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, /* set session auth for key */ if (dev->ctx.session) { wolfTPM2_SetAuthHandle(dev, 0, parent); + /* Make sure no other auth sessions exist */ + wolfTPM2_UnsetAuth(dev, 1); + wolfTPM2_UnsetAuth(dev, 2); } XMEMSET(&in, 0, sizeof(in)); diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 57dc4c8..b38a15a 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -2800,7 +2800,8 @@ WOLFTPM_API int TPM2_GetTpmCurve(int curveID); WOLFTPM_API int TPM2_GetWolfCurve(int curve_id); WOLFTPM_API int TPM2_ParseAttest(const TPM2B_ATTEST* in, TPMS_ATTEST* out); -WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name); +WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name); +WOLFTPM_API int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size); #ifdef WOLFTPM2_USE_WOLF_RNG WOLFTPM_API int TPM2_GetWolfRng(WC_RNG** rng); diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index ff8af90..901de9d 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -131,6 +131,7 @@ WOLFTPM_API int wolfTPM2_GetTpmDevId(WOLFTPM2_DEV* dev); WOLFTPM_API int wolfTPM2_SelfTest(WOLFTPM2_DEV* dev); WOLFTPM_API int wolfTPM2_GetCapabilities(WOLFTPM2_DEV* dev, WOLFTPM2_CAPS* caps); +WOLFTPM_API int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index); WOLFTPM_API int wolfTPM2_SetAuth(WOLFTPM2_DEV* dev, int index, TPM_HANDLE sessionHandle, const TPM2B_AUTH* auth, TPMA_SESSION sessionAttributes, const TPM2B_NAME* name); @@ -138,6 +139,7 @@ WOLFTPM_API int wolfTPM2_SetAuthPassword(WOLFTPM2_DEV* dev, int index, const TPM WOLFTPM_API int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); WOLFTPM_API int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes); +WOLFTPM_API int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); WOLFTPM_API int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, WOLFTPM2_KEY* tpmKey, From 3abe595b58348171e93500b02f8b1718f8c68704 Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Fri, 26 Feb 2021 10:35:46 +0200 Subject: [PATCH 5/8] Changes from peer review Signed-off-by: Dimitar Tomov --- src/tpm2.c | 28 ++++++++-------------- src/tpm2_wrap.c | 64 +++++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/tpm2.c b/src/tpm2.c index 9b7218d..87643ef 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -106,7 +106,7 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, CmdInfo_t* info, TPM_CC cmdCode, UINT32 cmdSz) { int rc = TPM_RC_SUCCESS; - UINT32 authSz; + UINT32 authSz, handleValue; BYTE *param, *encParam = NULL; int paramSz, encParamSz = 0; int i, authPos, handlePos; @@ -188,8 +188,6 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, } #ifndef WOLFTPM2_NO_WOLFCRYPT - UINT32 handleValue; - handlePos = packet->pos; packet->pos = TPM2_HEADER_SIZE; /* Handles are right after header */ TPM2_Packet_ParseU32(packet, &handleValue); @@ -5288,13 +5286,6 @@ int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2 session = &ctx->session[idx]; -#if 0 - if (session->name.size > 0) { - name->size = session->name.size; - XMEMCPY(name->name, session->name.name, name->size); - } - (void)handleValue; -#else if ((handleValue >= TRANSIENT_FIRST) || (handleValue >= NV_INDEX_FIRST && handleValue <= NV_INDEX_LAST)) { if (session->name.size > 0) { @@ -5307,7 +5298,6 @@ int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2 name->size = sizeof(handleValue); XMEMCPY(name->name, (byte*)&handleValue, name->size); } -#endif #ifdef WOLFTPM_DEBUG_VERBOSE printf("Name %d: %d\n", idx, name->size); @@ -5680,11 +5670,12 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) { int rc; #ifndef WOLFTPM2_NO_WOLFCRYPT - int hashSize, nameAlgValue, nameAlgSize; + int hashSize, nameAlgSize; + UINT16 nameAlgValue; wc_HashAlg hash; enum wc_HashType hashType; byte appending[sizeof(TPMS_NV_PUBLIC)]; - TPM2B_DIGEST digest; + TPM2B_DATA digest; TPM2_Packet packet; /* Prepare temporary buffer */ @@ -5711,7 +5702,7 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) hashSize = rc; rc = wc_HashInit(&hash, hashType); - if(rc == 0) { + if (rc == 0) { rc = wc_HashUpdate(&hash, hashType, packet.buf, packet.pos); } @@ -5726,13 +5717,14 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) XMEMCPY(&buffer[2], digest.buffer, hashSize); /* account for nameAlg concatenation */ *size = hashSize + nameAlgSize; + rc = TPM_RC_SUCCESS; } wc_HashFree(&hash, hashType); - return TPM_RC_SUCCESS; + return rc; #else - return TPM_RC_FAILURE; + return TPM_RC_SUCCESS; #endif } @@ -5781,10 +5773,10 @@ void TPM2_PrintAuth(const TPMS_AUTH_COMMAND* authCmd) return; printf("authCmd:\n"); - printf("sessionHandle=0x%7X\n", authCmd->sessionHandle); + printf("sessionHandle=0x%08X\n", authCmd->sessionHandle); printf("nonceSize=%u nonceBuffer:\n", authCmd->nonce.size); TPM2_PrintBin(authCmd->nonce.buffer, authCmd->nonce.size); - printf("sessionAttributes=0x%2X\n", authCmd->sessionAttributes); + printf("sessionAttributes=0x%02X\n", authCmd->sessionAttributes); printf("hmacSize=%u hmacBuffer:\n", authCmd->hmac.size); TPM2_PrintBin(authCmd->hmac.buffer, authCmd->hmac.size); } diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index e21df7e..f9e1378 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -26,10 +26,6 @@ /* For some struct to buffer conversions */ #include -#ifndef WOLFTPM2_NO_WOLFCRYPT -/* Required in wolfTPM2_CreateAuth() for name computation of NV handles */ -#include -#endif /* Local Functions */ @@ -378,7 +374,7 @@ int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index) { TPM2_AUTH_SESSION* session; - if (dev == NULL || index >= MAX_SESSION_NUM) { + if (dev == NULL || index >= MAX_SESSION_NUM || index < 0) { return BAD_FUNC_ARG; } @@ -394,7 +390,7 @@ int wolfTPM2_SetAuth(WOLFTPM2_DEV* dev, int index, { TPM2_AUTH_SESSION* session; - if (dev == NULL || index >= MAX_SESSION_NUM) { + if (dev == NULL || index >= MAX_SESSION_NUM || index < 0) { return BAD_FUNC_ARG; } @@ -2570,7 +2566,6 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, { int rc; NV_DefineSpace_In in; - TPM2B_NAME name; if (dev == NULL || nv == NULL) return BAD_FUNC_ARG; @@ -2580,7 +2575,6 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, wolfTPM2_SetAuthHandle(dev, 0, parent); } - XMEMSET(&name, 0, sizeof(name)); XMEMSET(&in, 0, sizeof(in)); in.authHandle = parent->hndl; if (auth && authSz > 0) { @@ -2609,14 +2603,18 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, } /* Compute NV Index name in case of parameter encryption */ - rc = TPM2_HashNvPublic(&in.publicInfo.nvPublic, name.name, &name.size); + rc = TPM2_HashNvPublic(&in.publicInfo.nvPublic, + (byte*)&nv->handle.name.name, + &nv->handle.name.size); + if (rc != TPM_RC_SUCCESS) { + return rc; + } /* return new NV handle */ XMEMSET(nv, 0, sizeof(*nv)); nv->handle.hndl = (TPM_HANDLE)nvIndex; nv->handle.auth = in.auth; - nv->handle.name.size = name.size; - XMEMCPY(&nv->handle.name.name, name.name, nv->handle.name.size); + /* nv->handle.name already populated by TPM2_HashNvPublic above */ #ifdef DEBUG_WOLFTPM printf("TPM2_NV_DefineSpace: Auth 0x%x, Idx 0x%x, Attribs 0x%d, Size %d\n", @@ -2650,8 +2648,7 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, int rc = TPM_RC_SUCCESS; word32 pos = 0, towrite; NV_Write_In in; - NV_ReadPublic_In inPublic; - NV_ReadPublic_Out outPublic; + TPMS_NV_PUBLIC nvPublic; if (dev == NULL || nv == NULL) return BAD_FUNC_ARG; @@ -2661,11 +2658,8 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } - XMEMSET((byte*)&inPublic, 0, sizeof(inPublic)); - XMEMSET((byte*)&outPublic, 0, sizeof(outPublic)); /* Read the NV Index publicArea to have up to date NV Index Name */ - inPublic.nvIndex = nv->handle.hndl; - rc = TPM2_NV_ReadPublic(&inPublic, &outPublic); + rc = wolfTPM2_NVReadPublic(dev, nv->handle.hndl, &nvPublic); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM printf("Failed to read fresh NvPublic\n"); @@ -2674,13 +2668,19 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, } /* Compute NV Index name in case of parameter encryption */ - rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic, - (byte*)&nv->handle.name.name, + rc = TPM2_HashNvPublic(&nvPublic, (byte*)&nv->handle.name.name, &nv->handle.name.size); + if (rc != TPM_RC_SUCCESS) { + return rc; + } /* Necessary, because NVWrite has two handles, second is NV Index */ - wolfTPM2_SetNameHandle(dev, 0, &nv->handle); - wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + rc = wolfTPM2_SetNameHandle(dev, 0, &nv->handle); + rc |= wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + if (rc != TPM_RC_SUCCESS) { + printf("Storing NV Index Name failed\n"); + return rc; + } while (dataSz > 0) { towrite = dataSz; @@ -2734,8 +2734,7 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 pos = 0, toread, dataSz; NV_Read_In in; NV_Read_Out out; - NV_ReadPublic_In inPublic; - NV_ReadPublic_Out outPublic; + TPMS_NV_PUBLIC nvPublic; if (dev == NULL || nv == NULL || pDataSz == NULL) return BAD_FUNC_ARG; @@ -2745,11 +2744,8 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } - XMEMSET((byte*)&inPublic, 0, sizeof(inPublic)); - XMEMSET((byte*)&outPublic, 0, sizeof(outPublic)); /* Read the NV Index publicArea to have up to date NV Index Name */ - inPublic.nvIndex = nv->handle.hndl; - rc = TPM2_NV_ReadPublic(&inPublic, &outPublic); + rc = wolfTPM2_NVReadPublic(dev, nv->handle.hndl, &nvPublic); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM printf("Failed to read fresh NvPublic\n"); @@ -2758,13 +2754,19 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, } /* Compute NV Index name in case of parameter encryption */ - rc = TPM2_HashNvPublic(&outPublic.nvPublic.nvPublic, - (byte*)&nv->handle.name.name, + rc = TPM2_HashNvPublic(&nvPublic, (byte*)&nv->handle.name.name, &nv->handle.name.size); + if (rc != TPM_RC_SUCCESS) { + return rc; + } /* Necessary, because NVWrite has two handles, second is NV Index */ - wolfTPM2_SetNameHandle(dev, 0, &nv->handle); - wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + rc = wolfTPM2_SetNameHandle(dev, 0, &nv->handle); + rc |= wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + if (rc != TPM_RC_SUCCESS) { + printf("Storing NV Index Name failed\n"); + return rc; + } dataSz = *pDataSz; From c18f421965ee538759775f37b41f7c32ef8329a5 Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Fri, 26 Feb 2021 11:38:17 +0200 Subject: [PATCH 6/8] Update the examples README Signed-off-by: Dimitar Tomov --- examples/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/examples/README.md b/examples/README.md index d11fff3..a0eb9c5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -44,6 +44,14 @@ More information about how to test and use PCR attestation can be found in the i ## Parameter Encryption +### Key generation with encrypted authorization + +Detailed information can be found in this file under section "Key generation" + +### Secure vault for keys with encrypted NVRAM authorization + +Detailed information can be found in this file under section "Storing keys into the TPM's NVRAM" + ### TPM2.0 Quote with encrypted user data Example for demonstrating how to use parameter encryption to protect the user data between the Host and the TPM. @@ -260,3 +268,29 @@ Loaded key to 0x80000001 ``` The `keyload` tool takes only one argument, the filename of the stored key. Because the information what is key scheme (RSA or ECC) is contained within the key blob. + +## Storing keys into the TPM's NVRAM + +These examples demonstrates how to use the TPM as secure vault for keys. There are two programs, one to store a TPM key into the TPM's NVRAM and another to extract the key from the TPM's NVRAM. Both examples can use parameter encryption to protect from MITM attacks. The Non-volatile memory location is protected with a password authorization that is passed in encrypted form, when "-aes" or "-xor" is given on the commmand line. + +Before running the examples, make sure there is a keyblob.bin generated using the keygen tool. The key can be of any type, RSA, ECC or symmetric. The example will store the private and public part. In case of a symmetric key the public part is meta data from the TPM. How to generate a key you can see above, in the description of the keygen example. + +Typical output for storing and then reading an RSA key using parameter encryption: + +``` +$ ./examples/nvram/store -aes +TPM2_StartAuthSession: sessionHandle 0x2000000 +Reading 840 bytes from keyblob.bin +Storing key at TPM NV index 0x1800203 with password protection +Public part = 616 bytes +Private part = 222 bytes +NV write succeeded + +$ ./examples/nvram/read 616 222 -aes +TPM2_StartAuthSession: sessionHandle 0x2000000 +Trying to read 616 bytes of public key part from NV +Trying to read 222 bytes of private key part from NV +Extraction of key from NVRAM at index 0x1800203 succeeded +``` + +The read example takes as first argument the size of the public part and as second argument the private part. This information is given from the store example. The "-aes" swiches triggers the use of parameter encryption. From e1d9c661bd64d9ccac2eab0debefd1313dda4662 Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Mon, 1 Mar 2021 10:30:33 +0200 Subject: [PATCH 7/8] Minor fixes for NVRAM examples Signed-off-by: Dimitar Tomov --- examples/README.md | 4 ++-- examples/nvram/read.c | 10 +++++----- examples/nvram/store.c | 8 ++++---- examples/tpm_test.h | 3 +-- src/tpm2.c | 5 ++--- src/tpm2_wrap.c | 16 ++++++++-------- wolftpm/tpm2_wrap.h | 2 +- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/examples/README.md b/examples/README.md index a0eb9c5..4cfe8c8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -281,7 +281,7 @@ Typical output for storing and then reading an RSA key using parameter encryptio $ ./examples/nvram/store -aes TPM2_StartAuthSession: sessionHandle 0x2000000 Reading 840 bytes from keyblob.bin -Storing key at TPM NV index 0x1800203 with password protection +Storing key at TPM NV index 0x1800202 with password protection Public part = 616 bytes Private part = 222 bytes NV write succeeded @@ -290,7 +290,7 @@ $ ./examples/nvram/read 616 222 -aes TPM2_StartAuthSession: sessionHandle 0x2000000 Trying to read 616 bytes of public key part from NV Trying to read 222 bytes of private key part from NV -Extraction of key from NVRAM at index 0x1800203 succeeded +Extraction of key from NVRAM at index 0x1800202 succeeded ``` The read example takes as first argument the size of the public part and as second argument the private part. This information is given from the store example. The "-aes" swiches triggers the use of parameter encryption. diff --git a/examples/nvram/read.c b/examples/nvram/read.c index 5a23365..8390561 100644 --- a/examples/nvram/read.c +++ b/examples/nvram/read.c @@ -120,28 +120,28 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) /* Prepare auth for NV Index */ XMEMSET(&nv, 0, sizeof(nv)); - nv.handle.hndl = TPM2_DEMO_NVRAM_STORE_PRIV_INDEX; + nv.handle.hndl = TPM2_DEMO_NVRAM_STORE_INDEX; nv.handle.auth.size = auth.size; XMEMCPY(nv.handle.auth.buffer, auth.buffer, auth.size); readSize = keyBlob.pub.size; printf("Trying to read %d bytes of public key part from NV\n", readSize); - rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX, (byte*)&keyBlob.pub.publicArea, &readSize, 0); if (rc != 0) goto exit; readSize = keyBlob.priv.size; printf("Trying to read %d bytes of private key part from NV\n", readSize); - rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX, (byte*)&keyBlob.priv.buffer, &readSize, keyBlob.pub.size); if (rc != 0) goto exit; parent.hndl = TPM_RH_OWNER; - rc = wolfTPM2_NVDeleteAuth(&dev, &parent, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + rc = wolfTPM2_NVDeleteAuth(&dev, &parent, TPM2_DEMO_NVRAM_STORE_INDEX); if (rc != 0) goto exit; printf("Extraction of key from NVRAM at index 0x%x succeeded\n" , - TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + TPM2_DEMO_NVRAM_STORE_INDEX); exit: diff --git a/examples/nvram/store.c b/examples/nvram/store.c index f61d4b0..3927e4d 100644 --- a/examples/nvram/store.c +++ b/examples/nvram/store.c @@ -116,20 +116,20 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) if (rc != 0) goto exit; /* Our wolfTPM2 wrapper for NV_Define */ - rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, TPM2_DEMO_NVRAM_STORE_INDEX, nvAttributes, TPM2_DEMO_NV_TEST_SIZE, (byte*)gNvAuth, sizeof(gNvAuth)-1); if (rc != 0 && rc != TPM_RC_NV_DEFINED) goto exit; printf("Storing key at TPM NV index 0x%x with password protection\n", - TPM2_DEMO_NVRAM_STORE_PRIV_INDEX); + TPM2_DEMO_NVRAM_STORE_INDEX); printf("Public part = %d bytes\n", keyBlob.pub.size); - rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX, (byte*)&keyBlob.pub.publicArea, keyBlob.pub.size, 0); if (rc != 0) goto exit; printf("Private part = %d bytes\n", keyBlob.priv.size); - rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_PRIV_INDEX, + rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX, keyBlob.priv.buffer, keyBlob.priv.size, keyBlob.pub.size); if (rc != 0) goto exit; diff --git a/examples/tpm_test.h b/examples/tpm_test.h index a9888dd..c6e9f9f 100755 --- a/examples/tpm_test.h +++ b/examples/tpm_test.h @@ -42,8 +42,7 @@ #define TPM2_DEMO_NV_TEST_INDEX 0x01800200 #define TPM2_DEMO_NV_TEST_AUTH_INDEX 0x01800201 -#define TPM2_DEMO_NVRAM_STORE_PUB_INDEX 0x01800202 -#define TPM2_DEMO_NVRAM_STORE_PRIV_INDEX 0x01800203 +#define TPM2_DEMO_NVRAM_STORE_INDEX 0x01800202 #define TPM2_DEMO_NV_TEST_SIZE 1024 /* max size on Infineon SLB9670 is 1664 */ static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth"; diff --git a/src/tpm2.c b/src/tpm2.c index 87643ef..98aec6d 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -5675,7 +5675,6 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) wc_HashAlg hash; enum wc_HashType hashType; byte appending[sizeof(TPMS_NV_PUBLIC)]; - TPM2B_DATA digest; TPM2_Packet packet; /* Prepare temporary buffer */ @@ -5707,14 +5706,14 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) } if (rc == 0) { - rc = wc_HashFinal(&hash, hashType, digest.buffer); + rc = wc_HashFinal(&hash, hashType, &buffer[2]); } if (rc == 0) { + /* Concatenate the nvPublic digest with nameAlg at the front */ nameAlgValue = TPM2_Packet_SwapU16(nvPublic->nameAlg); nameAlgSize = sizeof(nvPublic->nameAlg); XMEMCPY(buffer, (byte*)&nameAlgValue, nameAlgSize); - XMEMCPY(&buffer[2], digest.buffer, hashSize); /* account for nameAlg concatenation */ *size = hashSize + nameAlgSize; rc = TPM_RC_SUCCESS; diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index f9e1378..63eb83a 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -430,7 +430,7 @@ int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, return wolfTPM2_SetAuth(dev, index, TPM_RS_PW, auth, 0, name); } -int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index, +int wolfTPM2_SetAuthHandleName(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle) { const TPM2B_NAME* name = NULL; @@ -2602,6 +2602,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, return rc; } + XMEMSET(nv, 0, sizeof(*nv)); /* Compute NV Index name in case of parameter encryption */ rc = TPM2_HashNvPublic(&in.publicInfo.nvPublic, (byte*)&nv->handle.name.name, @@ -2611,7 +2612,6 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, } /* return new NV handle */ - XMEMSET(nv, 0, sizeof(*nv)); nv->handle.hndl = (TPM_HANDLE)nvIndex; nv->handle.auth = in.auth; /* nv->handle.name already populated by TPM2_HashNvPublic above */ @@ -2675,11 +2675,11 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, } /* Necessary, because NVWrite has two handles, second is NV Index */ - rc = wolfTPM2_SetNameHandle(dev, 0, &nv->handle); - rc |= wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + rc = wolfTPM2_SetAuthHandleName(dev, 0, &nv->handle); + rc |= wolfTPM2_SetAuthHandleName(dev, 1, &nv->handle); if (rc != TPM_RC_SUCCESS) { printf("Storing NV Index Name failed\n"); - return rc; + return TPM_RC_FAILURE; } while (dataSz > 0) { @@ -2761,11 +2761,11 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, } /* Necessary, because NVWrite has two handles, second is NV Index */ - rc = wolfTPM2_SetNameHandle(dev, 0, &nv->handle); - rc |= wolfTPM2_SetNameHandle(dev, 1, &nv->handle); + rc = wolfTPM2_SetAuthHandleName(dev, 0, &nv->handle); + rc |= wolfTPM2_SetAuthHandleName(dev, 1, &nv->handle); if (rc != TPM_RC_SUCCESS) { printf("Storing NV Index Name failed\n"); - return rc; + return TPM_RC_FAILURE; } dataSz = *pDataSz; diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 901de9d..001c344 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -139,7 +139,7 @@ WOLFTPM_API int wolfTPM2_SetAuthPassword(WOLFTPM2_DEV* dev, int index, const TPM WOLFTPM_API int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); WOLFTPM_API int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes); -WOLFTPM_API int wolfTPM2_SetNameHandle(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); +WOLFTPM_API int wolfTPM2_SetAuthHandleName(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); WOLFTPM_API int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, WOLFTPM2_KEY* tpmKey, From 228e8cfcecf3d3d66d50902b0d5e37bbb38bb01c Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Mon, 1 Mar 2021 22:45:27 +0200 Subject: [PATCH 8/8] Minor fixes for NVRAM examples when wolfCrypt is disabled Signed-off-by: Dimitar Tomov --- examples/tpm_test_keys.c | 2 ++ src/tpm2.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/tpm_test_keys.c b/examples/tpm_test_keys.c index f53fbec..d68d337 100644 --- a/examples/tpm_test_keys.c +++ b/examples/tpm_test_keys.c @@ -278,6 +278,7 @@ int getRSAkey(WOLFTPM2_DEV* pDev, } #else (void)pWolfRsaKey; + (void)tpmDevId; #endif /* !WOLFTPM2_NO_WOLFCRYPT && !NO_RSA */ return rc; @@ -311,6 +312,7 @@ int getECCkey(WOLFTPM2_DEV* pDev, } #else (void)pWolfEccKey; + (void)tpmDevId; #endif /* !WOLFTPM2_NO_WRAPPER && HAVE_ECC */ return rc; diff --git a/src/tpm2.c b/src/tpm2.c index 98aec6d..3958157 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -223,6 +223,9 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, #endif return rc; } + #else + (void)handleValue; + (void)handlePos; #endif } @@ -5668,8 +5671,8 @@ UINT16 TPM2_GetVendorID(void) /* Stores nameAlg + the digest of nvPublic in buffer, total size in size */ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) { - int rc; #ifndef WOLFTPM2_NO_WOLFCRYPT + int rc; int hashSize, nameAlgSize; UINT16 nameAlgValue; wc_HashAlg hash; @@ -5723,6 +5726,9 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size) return rc; #else + (void)nvPublic; + (void)buffer; + (void)size; return TPM_RC_SUCCESS; #endif }