diff --git a/examples/nvram/include.am b/examples/nvram/include.am index 4e1d5e0f..50fc4339 100644 --- a/examples/nvram/include.am +++ b/examples/nvram/include.am @@ -33,6 +33,12 @@ examples_nvram_extend_SOURCES = examples/nvram/extend.c \ examples/tpm_test_keys.c examples_nvram_extend_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) examples_nvram_extend_DEPENDENCIES = src/libwolftpm.la + +noinst_PROGRAMS += examples/nvram/nvauth +examples_nvram_nvauth_SOURCES = examples/nvram/nvauth.c \ + examples/tpm_test_keys.c +examples_nvram_nvauth_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_nvauth_DEPENDENCIES = src/libwolftpm.la endif example_nvramdir = $(exampledir)/nvram @@ -41,10 +47,12 @@ dist_example_nvram_DATA = \ examples/nvram/read.c \ examples/nvram/counter.c \ examples/nvram/policy_nv.c \ - examples/nvram/extend.c + examples/nvram/extend.c \ + examples/nvram/nvauth.c DISTCLEANFILES+= examples/nvram/.libs/store \ examples/nvram/.libs/read \ examples/nvram/.libs/counter \ examples/nvram/.libs/policy_nv \ - examples/nvram/.libs/extend + examples/nvram/.libs/extend \ + examples/nvram/.libs/nvauth diff --git a/examples/nvram/nvauth.c b/examples/nvram/nvauth.c new file mode 100644 index 00000000..1d239d84 --- /dev/null +++ b/examples/nvram/nvauth.c @@ -0,0 +1,351 @@ +/* nvauth.c + * + * Copyright (C) 2006-2025 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 3 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 NVRAM operations with authentication + * + * This example demonstrates creating, writing, reading, and deleting + * NV indices with owner authentication. It shows how to use + * owner authentication for write/delete operations while allowing + * unauthenticated reads. + * + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include +#include +#include + +#ifndef WOLFTPM2_NO_WRAPPER + +#include +#include +#include +#include + +/******************************************************************************/ +/* --- BEGIN TPM NVRAM Auth Example -- */ +/******************************************************************************/ +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/nvauth\n"); + printf("* -all Run all operations in order (create, write, read, delete)\n"); + printf("* -ownerauth[=] Auth for owner (optional)\n"); + printf("* -setownerauth Set owner auth\n"); + printf("* -create[=auth] Create NV index (optional: set nvIndex auth)\n"); + printf("* -write[=] Write value to NV index (optional: specify value, default: test)\n"); + printf("* -delete Delete NV index\n"); + printf("* -aes/xor: Enable Parameter Encryption\n"); +} + +int TPM2_NVRAM_Auth_Example(void* userCtx, int argc, char *argv[]) +{ + int rc = 0; + int i; + WOLFTPM2_DEV dev; + WOLFTPM2_SESSION session; + WOLFTPM2_NV nv; + word32 nvIndex = TPM2_DEMO_NVRAM_OWNER_INDEX; + byte buf[64]; + word32 bufLen = sizeof(buf); + int paramEncAlg = TPM_ALG_NULL; + const char* ownerAuthStr = NULL; + const char* nvIndexAuthStr = NULL; + WOLFTPM2_HANDLE owner; + WOLFTPM2_HANDLE nvIndexAuth; + + /* Command line flags */ + int do_create = 0; + int do_write = 0; + int do_read = 0; + int do_delete = 0; + const char* write_value = "test"; + int set_owner_auth = 0; + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + + /* Parse command line arguments */ + for (i = 1; i < argc; i++) { + /* Handle -ownerauth[=] */ + if (XSTRNCMP(argv[i], "-ownerauth=", XSTRLEN("-ownerauth=")) == 0) { + ownerAuthStr = argv[i] + XSTRLEN("-ownerauth="); + } + else if (XSTRCMP(argv[i], "-setownerauth") == 0) { + set_owner_auth = 1; + } + /* Handle -create[=auth] */ + else if (XSTRNCMP(argv[i], "-create=", XSTRLEN("-create=")) == 0) { + do_create = 1; + nvIndexAuthStr = argv[i] + XSTRLEN("-create="); + } + else if (XSTRCMP(argv[i], "-create") == 0) { + do_create = 1; + } + /* Handle -write[=] */ + else if (XSTRNCMP(argv[i], "-write=", XSTRLEN("-write=")) == 0) { + do_write = 1; + write_value = argv[i] + XSTRLEN("-write="); + } + else if (XSTRCMP(argv[i], "-write") == 0) { + do_write = 1; + } + else if (XSTRCMP(argv[i], "-read") == 0) { + do_read = 1; + } + else if (XSTRCMP(argv[i], "-delete") == 0) { + do_delete = 1; + } + else if (XSTRCMP(argv[i], "-all") == 0) { + do_create = 1; + do_write = 1; + do_read = 1; + do_delete = 1; + } + else if (XSTRCMP(argv[i], "-aes") == 0) { + paramEncAlg = TPM_ALG_CFB; + } + else if (XSTRCMP(argv[i], "-xor") == 0) { + paramEncAlg = TPM_ALG_XOR; + } + else { + printf("Warning: Unrecognized option: %s\n", argv[i]); + } + } + + printf("Example for NVRAM operations with authentication\n"); + printf("NV Index: 0x%x\n", nvIndex); + 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"); + } + + /* setup the owner authentication for NV write/delete */ + XMEMSET(&owner, 0, sizeof(owner)); + owner.hndl = TPM_RH_OWNER; + if (ownerAuthStr != NULL) { + owner.auth.size = (word16)XSTRLEN(ownerAuthStr); + XMEMCPY(owner.auth.buffer, ownerAuthStr, owner.auth.size); + } + + /* setup the nvIndex authentication */ + XMEMSET(&nvIndexAuth, 0, sizeof(nvIndexAuth)); + nvIndexAuth.hndl = nvIndex; + if (nvIndexAuthStr != NULL) { + nvIndexAuth.auth.size = (word16)XSTRLEN(nvIndexAuthStr); + XMEMCPY(nvIndexAuth.auth.buffer, nvIndexAuthStr, nvIndexAuth.auth.size); + } + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to initialize TPM: 0x%x\n", rc); + goto cleanup; + } + + if (paramEncAlg != TPM_ALG_NULL) { + rc = wolfTPM2_StartSession(&dev, &session, NULL, NULL, TPM_SE_HMAC, + paramEncAlg); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to start session: 0x%x\n", rc); + goto cleanup; + } + + rc = wolfTPM2_SetAuthSession(&dev, 1, &session, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to set auth session: 0x%x\n", rc); + goto cleanup; + } + } + + if (set_owner_auth) { + /* Example for setting the owner authentication */ + HierarchyChangeAuth_In in; + XMEMSET(&in, 0, sizeof(in)); + in.authHandle = owner.hndl; + in.newAuth.size = owner.auth.size; + XMEMCPY(in.newAuth.buffer, owner.auth.buffer, in.newAuth.size); + rc = TPM2_HierarchyChangeAuth(&in); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to set owner auth: 0x%x (%s), allowing error and " + "continuing as it might already be set\n", + rc, wolfTPM2_GetRCString(rc)); + rc = TPM_RC_SUCCESS; + } + printf("Owner hierarchy auth set\n"); + } + + if (do_create) { + /* Try to open an existing */ + rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, + nvIndexAuth.auth.buffer, nvIndexAuth.auth.size); + if (rc != TPM_RC_SUCCESS) { + /* Require owner password to write/delete and no password to read */ + word32 nvAttributes = + (TPMA_NV_AUTHREAD | TPMA_NV_OWNERWRITE | TPM_NT_ORDINARY); + /* Can also switch to using AUTHWRITE or OWNERREAD to flip permissions */ + + /* By default the nv auth handle is the nvIndex handle, + * but it can also be a hierarchy handle */ + nv.handle.hndl = owner.hndl; + /* Set auth for the owner hierarchy */ + wolfTPM2_SetAuthHandle(&dev, 0, &owner); + + /* if the NV is not found then create it */ + rc = wolfTPM2_NVCreateAuth(&dev, &owner, &nv, nvIndex, + nvAttributes, sizeof(buf), + nvIndexAuth.auth.buffer, nvIndexAuth.auth.size); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to create NV index: 0x%x\n", rc); + goto cleanup; + } + printf("Created NV index 0x%x\n", nvIndex); + } + else { + printf("NV index 0x%x already exists\n", nvIndex); + } + } + + if (do_write) { + rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, + nvIndexAuth.auth.buffer, nvIndexAuth.auth.size); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to open NV index for write: 0x%x\n", rc); + goto cleanup; + } + + /* By default the nv auth handle is the nvIndex handle, + * but it can also be a hierarchy handle */ + nv.handle.hndl = owner.hndl; + wolfTPM2_SetAuthHandle(&dev, 0, &owner); + wolfTPM2_SetAuthHandle(&dev, 1, &nvIndexAuth); + + bufLen = (word32)XSTRLEN(write_value)+1; + rc = wolfTPM2_NVWriteData(&dev, + (paramEncAlg != TPM_ALG_NULL) ? &session : NULL, + TPM_ALG_NULL, NULL, 0, &nv, nvIndex, (byte*)write_value, + bufLen, 0, NW_WRITE_FLAG_AUTH_CUSTOM); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to write to NV index: 0x%x\n", rc); + goto cleanup; + } + printf("Wrote %u bytes to NV index 0x%x\n", bufLen, nvIndex); + } + + if (do_read) { + TPMS_NV_PUBLIC nvPublic; + + /* Prepare auth for NV Index */ + XMEMSET(&nv, 0, sizeof(nv)); + + /* Clear all auth. Not required here, since wolfTPM2_NVReadAuth does it, + * but demonstrating that the auth is not required for a read because + * AUTHREAD is not set */ + wolfTPM2_SetAuthPassword(&dev, 0, NULL); + wolfTPM2_SetAuthPassword(&dev, 1, NULL); + + rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, + nvIndexAuth.auth.buffer, nvIndexAuth.auth.size); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to open NV index for read: 0x%x\n", rc); + goto cleanup; + } + + rc = wolfTPM2_NVReadPublic(&dev, nvIndex, &nvPublic); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to read public from NV index: 0x%x\n", rc); + goto cleanup; + } + bufLen = nvPublic.dataSize; + + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, buf, &bufLen, 0); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to read from NV index: 0x%x\n", rc); + goto cleanup; + } + + printf("Read %u bytes from NV index:\n", bufLen); + printf("Data: %s\n", buf); + } + + if (do_delete) { + wolfTPM2_SetAuthHandle(&dev, 0, &owner); + wolfTPM2_SetAuthHandle(&dev, 1, &nvIndexAuth); + + rc = wolfTPM2_NVDeleteAuth(&dev, &owner, nvIndex); + if (rc != TPM_RC_SUCCESS) { + printf("Failed to delete NV index: 0x%x\n", rc); + goto cleanup; + } + printf("Deleted NV index 0x%x\n", nvIndex); + } + +cleanup: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_UnsetAuth(&dev, 0); + if (paramEncAlg != TPM_ALG_NULL) { + wolfTPM2_UnloadHandle(&dev, &session.handle); + } + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM NVRAM Auth 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_Auth_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/nvram.h b/examples/nvram/nvram.h index 2f97832e..548522e9 100644 --- a/examples/nvram/nvram.h +++ b/examples/nvram/nvram.h @@ -33,6 +33,7 @@ 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[]); int TPM2_NVRAM_Extend_Example(void* userCtx, int argc, char *argv[]); +int TPM2_NVRAM_Auth_Example(void* userCtx, int argc, char *argv[]); #ifdef __cplusplus } /* extern "C" */ diff --git a/examples/tpm_test.h b/examples/tpm_test.h index afc1c339..fc4d18a6 100644 --- a/examples/tpm_test.h +++ b/examples/tpm_test.h @@ -45,6 +45,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_NVRAM_OWNER_INDEX 0x01800203 #define TPM2_DEMO_NVRAM_EXTEND_INDEX 0x01000200 #define TPM2_DEMO_NV_TEST_SIZE MAX_DIGEST_BUFFER /* max size on Infineon SLB9670 is 1664 */ #define TPM2_DEMO_NV_COUNTER_INDEX 0x01800300 @@ -73,6 +74,7 @@ static const char gKeyAuthAlt[] = "ThisIsMyKeyAltAuth"; static const char gUsageAuth[] = "ThisIsASecretUsageAuth"; static const char gNvAuth[] = "ThisIsMyNvAuth"; static const char gXorAuth[] = "ThisIsMyXorAuth"; +static const char gOwnerAuth[] = "ThisIsMyOwnerAuth"; static const char pemFileAk[] = PEM_FILE_AK; static const char pemFileEk[] = PEM_FILE_EK; diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 3c10706c..225aeb06 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -4749,6 +4749,33 @@ int wolfTPM2_UnloadHandle(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle) return TPM_RC_SUCCESS; } + +/******************************************************************************/ +/* --- Begin Wrapper NV Functions-- */ +/******************************************************************************/ + +static int wolfTPM2_NVComputeName(WOLFTPM2_DEV* dev, word32 nvIndex, + TPM2B_NAME* name, TPMA_NV* attributes) +{ + int rc; + TPMS_NV_PUBLIC nvPublic; + + /* Read the NV Index publicArea to have up to date NV Index Name */ + rc = wolfTPM2_NVReadPublic(dev, nvIndex, &nvPublic); + if (rc == TPM_RC_SUCCESS) { + if (attributes != NULL) { + *attributes = nvPublic.attributes; + } + #ifndef WOLFTPM2_NO_WOLFCRYPT + /* Compute NV Index name in case of parameter encryption */ + rc = TPM2_HashNvPublic(&nvPublic, (byte*)&name->name, &name->size); + #else + (void)name; /* not used */ + #endif + } + return rc; +} + /* nv is the populated handle and auth */ /* auth and authSz are optional NV authentication */ /* authPolicy and authPolicySz are optional policy digest */ @@ -4850,9 +4877,9 @@ int wolfTPM2_NVCreate(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, maxSize, auth, authSz); } -static int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, +int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, WOLFTPM2_NV* nv, - word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset, int extend) + word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset, word32 flags) { int rc = TPM_RC_SUCCESS; word32 pos = 0, towrite; @@ -4874,7 +4901,7 @@ static int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, * Name changes on each iteration for policy session. * If this is the first write to NV then the NV_WRITTEN bit will get * set and name needs re-computed */ - rc = wolfTPM2_NVOpen(dev, nv, nvIndex, NULL, 0); + rc = wolfTPM2_NVComputeName(dev, nvIndex, &nv->handle.name, NULL); if (rc != 0) break; /* For policy session recompute PCR for each iteration */ @@ -4890,16 +4917,18 @@ static int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, wolfTPM2_SetSessionHandle(dev, 0, tpmSession); } - /* Necessary, because NVWrite has two handles, second is NV Index - * If policy session Name will update via nonceTPM each iteration */ - rc = wolfTPM2_SetAuthHandleName(dev, 0, &nv->handle); - rc |= wolfTPM2_SetAuthHandleName(dev, 1, &nv->handle); - if (rc != TPM_RC_SUCCESS) { - #ifdef DEBUG_WOLFTPM - printf("wolfTPM2_NVWriteData: Setting NV index name failed\n"); - #endif - rc = TPM_RC_FAILURE; - break; + if (!(flags & NW_WRITE_FLAG_AUTH_CUSTOM)) { + /* Necessary, because NVWrite has two handles, second is NV Index + * If policy session Name will update via nonceTPM each iteration */ + rc = wolfTPM2_SetAuthHandleName(dev, 0, &nv->handle); + rc |= wolfTPM2_SetAuthHandleName(dev, 1, &nv->handle); + if (rc != TPM_RC_SUCCESS) { + #ifdef DEBUG_WOLFTPM + printf("wolfTPM2_NVWriteData: Setting NV index name failed\n"); + #endif + rc = TPM_RC_FAILURE; + break; + } } XMEMSET(&in, 0, sizeof(in)); @@ -4908,7 +4937,7 @@ static int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, in.write.data.size = towrite; if (dataBuf) XMEMCPY(in.write.data.buffer, &dataBuf[pos], towrite); - if (!extend) { + if (!(flags & NW_WRITE_FLAG_EXTEND)) { in.write.offset = offset+pos; } @@ -4916,10 +4945,10 @@ static int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, printf("wolfTPM2_NVWriteData: Auth 0x%x, Idx 0x%x, Offset %d, Size %d, " "Extend %d\n", (word32)in.write.authHandle, (word32)in.write.nvIndex, - in.write.offset, in.write.data.size, extend); + in.write.offset, in.write.data.size, flags & NW_WRITE_FLAG_EXTEND); #endif - if (!extend) { + if (!(flags & NW_WRITE_FLAG_EXTEND)) { rc = TPM2_NV_Write(&in.write); } else { @@ -4947,7 +4976,7 @@ int wolfTPM2_NVExtend(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32 dataSz) { return wolfTPM2_NVWriteData(dev, NULL, TPM_ALG_NULL, NULL, 0, - nv, nvIndex, dataBuf, dataSz, 0, 1); + nv, nvIndex, dataBuf, dataSz, 0, NW_WRITE_FLAG_EXTEND); } int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, @@ -4955,14 +4984,14 @@ int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset) { return wolfTPM2_NVWriteData(dev, tpmSession, pcrAlg, pcrArray, pcrArraySz, - nv, nvIndex, dataBuf, dataSz, offset, 0); + nv, nvIndex, dataBuf, dataSz, offset, NW_WRITE_FLAG_NONE); } int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset) { return wolfTPM2_NVWriteData(dev, NULL, TPM_ALG_NULL, NULL, 0, - nv, nvIndex, dataBuf, dataSz, offset, 0); + nv, nvIndex, dataBuf, dataSz, offset, NW_WRITE_FLAG_NONE); } /* older API kept for compatibility, recommend using wolfTPM2_NVWriteAuth */ @@ -4999,7 +5028,7 @@ int wolfTPM2_NVReadAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, * Name changes on each iteration for policy session. */ if (!nv->handle.nameLoaded || (tpmSession != NULL && TPM2_IS_POLICY_SESSION(tpmSession->handle.hndl))) { - rc = wolfTPM2_NVOpen(dev, nv, nvIndex, NULL, 0); + rc = wolfTPM2_NVComputeName(dev, nvIndex, &nv->handle.name, NULL); if (rc != 0) break; } @@ -5134,8 +5163,7 @@ int wolfTPM2_NVRead(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, int wolfTPM2_NVOpen(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, const byte* auth, word32 authSz) { - int rc = TPM_RC_SUCCESS; - TPMS_NV_PUBLIC nvPublic; + int rc; if (dev == NULL || nv == NULL || authSz > sizeof(nv->handle.auth.buffer)) { return BAD_FUNC_ARG; @@ -5151,27 +5179,12 @@ int wolfTPM2_NVOpen(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, XMEMCPY(nv->handle.auth.buffer, auth, nv->handle.auth.size); } - /* 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 open (read) NV\n"); - #endif - return rc; - } - /* Compute NV Index name in case of parameter encryption */ -#ifndef WOLFTPM2_NO_WOLFCRYPT - rc = TPM2_HashNvPublic(&nvPublic, (byte*)&nv->handle.name.name, - &nv->handle.name.size); - if (rc != TPM_RC_SUCCESS) { - return rc; + rc = wolfTPM2_NVComputeName(dev, nvIndex, &nv->handle.name, &nv->attributes); + if (rc == TPM_RC_SUCCESS) { + /* flag that the NV was "opened" and name was loaded */ + nv->handle.nameLoaded = 1; } -#endif - - /* flag that the NV was "opened" and name was loaded */ - nv->handle.nameLoaded = 1; - nv->attributes = nvPublic.attributes; return rc; } @@ -5343,6 +5356,11 @@ int wolfTPM2_NVDelete(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, return wolfTPM2_NVDeleteAuth(dev, &parent, nvIndex); } +/******************************************************************************/ +/* --- END Wrapper NV Functions-- */ +/******************************************************************************/ + + #ifndef WOLFTPM2_NO_WOLFCRYPT struct WC_RNG* wolfTPM2_GetRng(WOLFTPM2_DEV* dev) { diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 8d709baa..7c8781be 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -2097,6 +2097,48 @@ WOLFTPM_API int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* WOLFTPM_API int wolfTPM2_NVExtend(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32 dataSz); +/* Flags for wolfTPM2_NVWriteData */ +#define NW_WRITE_FLAG_NONE 0x00 +#define NW_WRITE_FLAG_EXTEND 0x01 +#define NW_WRITE_FLAG_AUTH_CUSTOM 0x02 + +/*! + \ingroup wolfTPM2_Wrappers + \brief Stores user data to a NV Index at a given offset. Supports policy sessions with PCR authentication, extend operations, and regular writes. + \note User data size should be less or equal to the NV Index maxSize specified using wolfTPM2_CreateAuth + \note This is a general-purpose function that can be used for regular writes (when tpmSession is NULL and flags is NW_WRITE_FLAG_NONE), extend operations (when flags includes NW_WRITE_FLAG_EXTEND), or policy-based writes (when tpmSession is provided) + \note For policy sessions, PCR policy is recomputed for each write iteration to handle large data writes + + \return TPM_RC_SUCCESS: successful + \return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code) + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a TPM2_DEV struct + \param tpmSession pointer to a WOLFTPM2_SESSION struct used with wolfTPM2_StartSession and wolfTPM2_SetAuthSession. Can be NULL for regular authentication + \param pcrAlg the hash algorithm to use with PCR policy (TPM_ALG_NULL if not using PCR authentication) + \param pcrArray array of PCR Indexes to use when creating the policy. Can be NULL if not using PCR authentication + \param pcrArraySz the number of PCR Indexes in the pcrArray. Should be 0 if not using PCR authentication + \param nv pointer to a populated structure of WOLFTPM2_NV type + \param nvIndex integer value, holding an existing NV Index Handle value + \param dataBuf pointer to a byte buffer, containing the user data to be written to the TPM's NVRAM + \param dataSz integer value, specifying the size of the user data buffer, in bytes + \param offset integer value of word32 type, specifying the offset from the NV Index memory start, can be zero + \param flags bit flags for controlling write behavior. Flags can be combined using bitwise OR: + NW_WRITE_FLAG_NONE (0x00) for regular write, + NW_WRITE_FLAG_EXTEND (0x01) for extend operation + NW_WRITE_FLAG_AUTH_CUSTOM (0x02) to skip setting auth (it must be done manually prior to calling) + + \sa wolfTPM2_NVWriteAuth + \sa wolfTPM2_NVWriteAuthPolicy + \sa wolfTPM2_NVExtend + \sa wolfTPM2_NVReadAuth + \sa wolfTPM2_NVCreateAuth + \sa wolfTPM2_NVDeleteAuth +*/ +WOLFTPM_API int wolfTPM2_NVWriteData(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, + TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, WOLFTPM2_NV* nv, + word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset, word32 flags); + /*! \ingroup wolfTPM2_Wrappers \brief Reads user data from a NV Index, starting at the given offset