From df13479ac77618d7a3f906bf7046631690e1bcbb Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Tue, 9 Feb 2021 22:19:50 +0200 Subject: [PATCH] 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 eab540d6..edadd6fc 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 00000000..cf401c11 --- /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 00000000..5a233659 --- /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 00000000..f61d4b0e --- /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 00000000..85a3121b --- /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 f6686af9..a9888dda 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";