diff --git a/examples/README.md b/examples/README.md index d11fff3..4cfe8c8 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 0x1800202 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 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/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..8390561 --- /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_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_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_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_INDEX); + if (rc != 0) goto exit; + + printf("Extraction of key from NVRAM at index 0x%x succeeded\n" , + TPM2_DEMO_NVRAM_STORE_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..3927e4d --- /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_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_INDEX); + + printf("Public part = %d bytes\n", keyBlob.pub.size); + 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_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..c6e9f9f 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,7 @@ #define TPM2_DEMO_NV_TEST_INDEX 0x01800200 #define TPM2_DEMO_NV_TEST_AUTH_INDEX 0x01800201 +#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/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 27fe2a1..3958157 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -106,9 +106,10 @@ 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, 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,14 @@ 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); + 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"); @@ -217,6 +223,9 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet, #endif return rc; } + #else + (void)handleValue; + (void)handlePos; #endif } @@ -4609,9 +4618,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); @@ -5268,7 +5278,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; @@ -5278,10 +5288,20 @@ int TPM2_GetName(TPM2_CTX* ctx, int handleCnt, int idx, TPM2B_NAME* name) return TPM_RC_SUCCESS; session = &ctx->session[idx]; - if (session->name.size > 0) { - name->size = session->name.size; - XMEMCPY(name->name, session->name.name, name->size); + + 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); + } + #ifdef WOLFTPM_DEBUG_VERBOSE printf("Name %d: %d\n", idx, name->size); TPM2_PrintBin(name->name, name->size); @@ -5648,6 +5668,71 @@ 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) +{ +#ifndef WOLFTPM2_NO_WOLFCRYPT + int rc; + int hashSize, nameAlgSize; + UINT16 nameAlgValue; + wc_HashAlg hash; + enum wc_HashType hashType; + byte appending[sizeof(TPMS_NV_PUBLIC)]; + 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, &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); + /* account for nameAlg concatenation */ + *size = hashSize + nameAlgSize; + rc = TPM_RC_SUCCESS; + } + + wc_HashFree(&hash, hashType); + + return rc; +#else + (void)nvPublic; + (void)buffer; + (void)size; + return TPM_RC_SUCCESS; +#endif +} + #ifdef DEBUG_WOLFTPM #define LINE_LEN 16 void TPM2_PrintBin(const byte* buffer, word32 length) @@ -5686,6 +5771,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%08X\n", authCmd->sessionHandle); + printf("nonceSize=%u nonceBuffer:\n", authCmd->nonce.size); + TPM2_PrintBin(authCmd->nonce.buffer, authCmd->nonce.size); + printf("sessionAttributes=0x%02X\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..1260f52 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -320,6 +320,10 @@ 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 && (authCmd->sessionAttributes & TPMA_SESSION_continueSession) == 0) { diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index af20660..63eb83a 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -27,6 +27,7 @@ /* For some struct to buffer conversions */ #include + /* Local Functions */ static int wolfTPM2_GetCapabilities_NoDev(WOLFTPM2_CAPS* cap); @@ -369,13 +370,27 @@ 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 || index < 0) { + 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) { TPM2_AUTH_SESSION* session; - if (dev == NULL || index >= MAX_SESSION_NUM) { + if (dev == NULL || index >= MAX_SESSION_NUM || index < 0) { return BAD_FUNC_ARG; } @@ -415,6 +430,24 @@ int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, return wolfTPM2_SetAuth(dev, index, TPM_RS_PW, auth, 0, name); } +int wolfTPM2_SetAuthHandleName(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 +479,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; } @@ -2560,9 +2602,19 @@ 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, + &nv->handle.name.size); + if (rc != TPM_RC_SUCCESS) { + return rc; + } + /* return new NV handle */ nv->handle.hndl = (TPM_HANDLE)nvIndex; nv->handle.auth = in.auth; + /* 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", @@ -2596,6 +2648,7 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, int rc = TPM_RC_SUCCESS; word32 pos = 0, towrite; NV_Write_In in; + TPMS_NV_PUBLIC nvPublic; if (dev == NULL || nv == NULL) return BAD_FUNC_ARG; @@ -2605,6 +2658,30 @@ int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } + /* Read the NV Index publicArea to have up to date NV Index Name */ + rc = wolfTPM2_NVReadPublic(dev, nv->handle.hndl, &nvPublic); + 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(&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 */ + 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 TPM_RC_FAILURE; + } + 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,7 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 pos = 0, toread, dataSz; NV_Read_In in; NV_Read_Out out; + TPMS_NV_PUBLIC nvPublic; if (dev == NULL || nv == NULL || pDataSz == NULL) return BAD_FUNC_ARG; @@ -2665,6 +2744,30 @@ int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, wolfTPM2_SetAuthHandle(dev, 0, &nv->handle); } + /* Read the NV Index publicArea to have up to date NV Index Name */ + rc = wolfTPM2_NVReadPublic(dev, nv->handle.hndl, &nvPublic); + 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(&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 */ + 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 TPM_RC_FAILURE; + } + dataSz = *pDataSz; while (dataSz > 0) { @@ -2773,6 +2876,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)); @@ -3768,9 +3874,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) { diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 34dad54..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); @@ -2819,8 +2820,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 diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index ff8af90..001c344 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_SetAuthHandleName(WOLFTPM2_DEV* dev, int index, const WOLFTPM2_HANDLE* handle); WOLFTPM_API int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, WOLFTPM2_KEY* tpmKey,