diff --git a/.gitignore b/.gitignore index 8693e89b..1206f4d0 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ examples/keygen/external_import examples/nvram/store examples/nvram/read examples/nvram/counter +examples/nvram/policy_nv examples/gpio/gpio_config examples/gpio/gpio_set examples/gpio/gpio_read diff --git a/examples/nvram/counter.c b/examples/nvram/counter.c index 958d1ae9..4fca5cec 100644 --- a/examples/nvram/counter.c +++ b/examples/nvram/counter.c @@ -128,7 +128,7 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[]) if (paramEncAlg != TPM_ALG_NULL) { /* Start TPM session for parameter encryption */ rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, - TPM_SE_HMAC, TPM_ALG_CFB); + TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", (word32)tpmSession.handle.hndl); diff --git a/examples/nvram/include.am b/examples/nvram/include.am index 596bdd60..4e8146aa 100644 --- a/examples/nvram/include.am +++ b/examples/nvram/include.am @@ -18,17 +18,25 @@ examples_nvram_read_DEPENDENCIES = src/libwolftpm.la noinst_PROGRAMS += examples/nvram/counter examples_nvram_counter_SOURCES = examples/nvram/counter.c \ - examples/tpm_test_keys.c + examples/tpm_test_keys.c examples_nvram_counter_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) examples_nvram_counter_DEPENDENCIES = src/libwolftpm.la + +noinst_PROGRAMS += examples/nvram/policy_nv +examples_nvram_policy_nv_SOURCES = examples/nvram/policy_nv.c \ + examples/tpm_test_keys.c +examples_nvram_policy_nv_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_policy_nv_DEPENDENCIES = src/libwolftpm.la endif example_nvramdir = $(exampledir)/nvram dist_example_nvram_DATA = \ examples/nvram/store.c \ examples/nvram/read.c \ - examples/nvram/counter.c + examples/nvram/counter.c \ + examples/nvram/policy_nv.c DISTCLEANFILES+= examples/nvram/.libs/store DISTCLEANFILES+= examples/nvram/.libs/read DISTCLEANFILES+= examples/nvram/.libs/counter +DISTCLEANFILES+= examples/nvram/.libs/policy_nv diff --git a/examples/nvram/nvram.h b/examples/nvram/nvram.h index 20d9cc68..aa92c307 100644 --- a/examples/nvram/nvram.h +++ b/examples/nvram/nvram.h @@ -31,6 +31,7 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]); int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[]); int TPM2_PCR_Seal_With_Policy_Auth_NV_Test(void* userCtx, int argc, char *argv[]); int TPM2_PCR_Seal_With_Policy_Auth_NV_External_Test(void* userCtx, int argc, char *argv[]); +int TPM2_NVRAM_PolicyNV_Example(void* userCtx, int argc, char *argv[]); #ifdef __cplusplus } /* extern "C" */ diff --git a/examples/nvram/policy_nv.c b/examples/nvram/policy_nv.c new file mode 100644 index 00000000..a7c25ded --- /dev/null +++ b/examples/nvram/policy_nv.c @@ -0,0 +1,305 @@ +/* policy_nv.c + * + * Copyright (C) 2006-2023 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-1335, 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 + +#ifndef WOLFTPM2_NO_WRAPPER + +#include +#include +#include +#include + +/******************************************************************************/ +/* --- BEGIN TPM NVRAM Policy NV Example -- */ +/******************************************************************************/ + +#if 1 +#define TPM2_DEMO_POLICY_NVINDEX 0x1500001 +#define TPM2_DEMO_POLICY_AUTH TPM_RH_OWNER +#else +#define TPM2_DEMO_POLICY_NVINDEX 0x1000000 +#define TPM2_DEMO_POLICY_AUTH TPM_RH_PLATFORM +#endif + + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/policy_nv [-data=] [-nvindex] [-aes/-xor]\n"); + printf("* -data=[filename]: data store (default 1 byte = 0xAA)\n"); + printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_POLICY_NVINDEX); + printf("* -aes/xor: Use Parameter Encryption\n"); +} + +int TPM2_NVRAM_PolicyNV_Example(void* userCtx, int argc, char *argv[]) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_HANDLE parent; + WOLFTPM2_NV nv; + word32 nvAttributes; + TPMI_RH_NV_AUTH authHandle = TPM2_DEMO_POLICY_AUTH; + int paramEncAlg = TPM_ALG_NULL; + word32 nvIndex = TPM2_DEMO_POLICY_NVINDEX; + TPMA_SESSION sessionAttributes; + byte* buf = NULL; + size_t bufLen = 0; + PolicyNV_In policyNvIn; + const byte testData[1] = {0xAA}; + const char* filename = NULL; + TPM2B_AUTH auth; + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + while (argc > 1) { + if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) { + const char* nvIndexStr = argv[argc-1] + XSTRLEN("-nvindex="); + nvIndex = (word32)XSTRTOL(nvIndexStr, NULL, 0); + if (!(authHandle == TPM_RH_PLATFORM && ( + nvIndex > TPM_20_PLATFORM_MFG_NV_SPACE && + nvIndex < TPM_20_OWNER_NV_SPACE)) && + !(authHandle == TPM_RH_OWNER && ( + nvIndex > TPM_20_OWNER_NV_SPACE && + nvIndex < TPM_20_TCG_NV_SPACE))) + { + fprintf(stderr, "Invalid NV Index %s\n", nvIndexStr); + fprintf(stderr, "\tPlatform Range: 0x%x -> 0x%x\n", + TPM_20_PLATFORM_MFG_NV_SPACE, TPM_20_OWNER_NV_SPACE); + fprintf(stderr, "\tOwner Range: 0x%x -> 0x%x\n", + TPM_20_OWNER_NV_SPACE, TPM_20_TCG_NV_SPACE); + usage(); + return -1; + } + } + else if (XSTRCMP(argv[argc-1], "-aes") == 0) { + paramEncAlg = TPM_ALG_CFB; + } + else if (XSTRCMP(argv[argc-1], "-xor") == 0) { + paramEncAlg = TPM_ALG_XOR; + } + else if (XSTRNCMP(argv[argc-1], "-data=", + XSTRLEN("-data=")) == 0) { + filename = argv[argc-1] + XSTRLEN("-data="); + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } + argc--; + }; + + if (paramEncAlg == TPM_ALG_CFB) { + printf("Parameter Encryption: Enabled. (AES CFB)\n\n"); + } + else if (paramEncAlg == TPM_ALG_XOR) { + printf("Parameter Encryption: Enabled. (XOR)\n\n"); + } + else { + printf("Parameter Encryption: Not enabled (try -aes or -xor).\n\n"); + } + + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&parent, 0, sizeof(parent)); + XMEMSET(&auth, 0, sizeof(auth)); + + auth.size = sizeof(gNvAuth)-1; + if (auth.size > sizeof(auth.buffer)) + auth.size = sizeof(auth.buffer); + XMEMCPY(auth.buffer, gNvAuth, auth.size); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + + /* Start TPM session and optional parameter encryption */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_HMAC, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + sessionAttributes = TPMA_SESSION_continueSession; + if (paramEncAlg != TPM_ALG_NULL) { + sessionAttributes |= (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt); + } + + /* Set TPM session attributes for parameter encryption */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, sessionAttributes); + if (rc != 0) goto exit; + + if (filename != NULL) { + rc = loadFile(filename, &buf, &bufLen); + if (rc != 0) goto exit; + } + else { + buf = (byte*)testData; + bufLen = (word32)sizeof(testData); + } + if (bufLen > (word32)sizeof(policyNvIn.operandB.buffer)) { + bufLen = (word32)sizeof(policyNvIn.operandB.buffer); + } + + /* Prepare NV_AUTHWRITE and NV_AUTHREAD attributes necessary for password */ + parent.hndl = authHandle; + rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes); + if (rc != 0) goto exit; + + /* Our wolfTPM2 wrapper for NV_Define */ + rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, nvIndex, + nvAttributes, (word32)bufLen, auth.buffer, auth.size); + if (rc != 0 && rc != TPM_RC_NV_DEFINED) goto exit; + + printf("Storing data at TPM NV index 0x%x with password protection\n\n", + nvIndex); + + rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, buf, (word32)bufLen, 0); + if (rc != 0) goto exit; + + printf("Write %d bytes to NV index 0x%x\n", (int)bufLen, nvIndex); + + /* Close session */ + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_UnsetAuth(&dev, 1); + + + /* BEGIN TPM2_PolicyNV test */ + + /* Start TPM policy session and optional parameter encryption */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* Setup PolicyNV Command */ + XMEMSET(&policyNvIn, 0, sizeof(policyNvIn)); + wolfTPM2_SetAuthHandle(&dev, 0, &parent); + policyNvIn.authHandle = parent.hndl; + wolfTPM2_SetAuthHandleName(&dev, 1, &nv.handle); + policyNvIn.nvIndex = nvIndex; + policyNvIn.policySession = tpmSession.handle.hndl; + rc = wolfTPM2_SetAuthSession(&dev, 2, &tpmSession, sessionAttributes); + if (rc != 0) goto exit; + + policyNvIn.offset = 0; + policyNvIn.operation = TPM_EO_EQ; + policyNvIn.operandB.size = bufLen; + XMEMCPY(policyNvIn.operandB.buffer, buf, bufLen); + + rc = TPM2_PolicyNV(&policyNvIn); + if (rc != 0) goto exit; + + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + /* Test again and it should fail! */ + /* Start TPM policy session and optional parameter encryption */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + 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, 2, &tpmSession, sessionAttributes); + if (rc != 0) goto exit; + + /* Setup PolicyNV Command */ + XMEMSET(&policyNvIn, 0, sizeof(policyNvIn)); + wolfTPM2_SetAuthHandle(&dev, 0, &parent); + policyNvIn.authHandle = parent.hndl; + wolfTPM2_SetAuthHandleName(&dev, 1, &nv.handle); + policyNvIn.nvIndex = nvIndex; + policyNvIn.policySession = tpmSession.handle.hndl; + rc = wolfTPM2_SetAuthSession(&dev, 2, &tpmSession, sessionAttributes); + if (rc != 0) goto exit; + + policyNvIn.offset = 0; + policyNvIn.operation = TPM_EO_EQ; + policyNvIn.operandB.size = 1; + policyNvIn.operandB.buffer[0] = 0xBB; + rc = TPM2_PolicyNV(&policyNvIn); + if (rc == TPM_RC_POLICY) { + /* policy failure is expected here */ + rc = 0; + } + else { + printf("The policy NV should have failed here!\n"); + rc = TPM_RC_POLICY; + goto exit; + } + /* END TPM2_PolicyNV test */ + + printf("TPM2_PolicyNV test passed\n"); + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + if (buf != testData) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM NVRAM Policy NV 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_PolicyNV_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/read.c b/examples/nvram/read.c index a0a20eb0..c787ef81 100644 --- a/examples/nvram/read.c +++ b/examples/nvram/read.c @@ -144,7 +144,7 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) if (paramEncAlg != TPM_ALG_NULL) { /* Start TPM session for parameter encryption */ rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, - TPM_SE_HMAC, TPM_ALG_CFB); + TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", (word32)tpmSession.handle.hndl); diff --git a/examples/nvram/store.c b/examples/nvram/store.c index b0251682..9fbd488d 100644 --- a/examples/nvram/store.c +++ b/examples/nvram/store.c @@ -117,7 +117,7 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-pub") == 0) { partialStore = PUBLIC_PART_ONLY; } - else { + else if (argv[argc-1][0] == '-') { printf("Warning: Unrecognized option: %s\n", argv[argc-1]); } argc--; @@ -146,7 +146,7 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) if (paramEncAlg != TPM_ALG_NULL) { /* Start TPM session for parameter encryption */ rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, - TPM_SE_HMAC, TPM_ALG_CFB); + TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", (word32)tpmSession.handle.hndl); diff --git a/examples/run_examples.sh b/examples/run_examples.sh index f983b933..a294670a 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -138,6 +138,13 @@ RESULT=$? RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read pub only failed! $RESULT" && exit 1 +./examples/nvram/policy_nv >> run.out +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "nv policy nv failed! $RESULT" && exit 1 +./examples/nvram/policy_nv -aes >> run.out +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "nv policy nv aes failed! $RESULT" && exit 1 + # CSR Tests ./examples/keygen/keygen rsa_test_blob.raw -rsa -t >> run.out