diff --git a/examples/gpio/gpio_config.c b/examples/gpio/gpio_config.c index 189d3d73..4be4d4b1 100644 --- a/examples/gpio/gpio_config.c +++ b/examples/gpio/gpio_config.c @@ -406,7 +406,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes); /* Add NV attributes required by Nuvoton specification */ nvAttributes |= (TPMA_NV_PLATFORMCREATE | TPMA_NV_POLICY_DELETE); - nvAttributes |= (TPM_NT_ORDINARY & TPMA_NV_TPM_NT); + nvAttributes |= (TPMA_NV_TPM_NT & (TPM_NT_ORDINARY << 4)); if (rc != TPM_RC_SUCCESS) { printf("Setting NV attributes failed\n"); goto exit; diff --git a/examples/nvram/read.c b/examples/nvram/read.c index 7dce5993..3399e4cb 100644 --- a/examples/nvram/read.c +++ b/examples/nvram/read.c @@ -50,12 +50,13 @@ static void usage(void) { printf("Expected usage:\n"); - printf("./examples/nvram/read [-nvindex] [-priv] [-pub] [-aes/-xor]\n"); + printf("./examples/nvram/read [-nvindex] [-priv] [-pub] [-aes/-xor] [-delete]\n"); printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_NVRAM_STORE_INDEX); printf("* -priv: Read ony the private part\n"); printf("* -pub: Read only the public part\n"); printf("* -aes/xor: Use Parameter Encryption\n"); printf("* -endorsement/platform/owner: Auth hierarchy\n"); + printf("* -delete: Remove NV\n"); } int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) @@ -77,6 +78,8 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)]; int pubAreaSize; word32 nvIndex = TPM2_DEMO_NVRAM_STORE_INDEX; + int deleteKey = 0; + int nvExtend = 0; if (argc >= 2) { if (XSTRCMP(argv[1], "-?") == 0 || @@ -121,6 +124,9 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-pub") == 0) { partialRead = PUBLIC_PART_ONLY; } + else if (XSTRCMP(argv[argc-1], "-delete") == 0) { + deleteKey = 1; + } else { printf("Warning: Unrecognized option: %s\n", argv[argc-1]); } @@ -176,71 +182,91 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[]) nv.handle.auth.size = auth.size; XMEMCPY(nv.handle.auth.buffer, auth.buffer, auth.size); - if (partialRead != PRIVATE_PART_ONLY) { - readSize = sizeof(keyBlob.pub.size); - printf("Trying to read %d bytes of public key size marker\n", readSize); - rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, - (byte*)&keyBlob.pub.size, &readSize, 0); - if (rc != 0) { - printf("Was a public key part written? (see nvram/store)\n"); - goto exit; - } - printf("Successfully read public key part from NV\n\n"); - offset += readSize; - - readSize = sizeof(UINT16) + keyBlob.pub.size; /* account for TPM2B size marker */ - printf("Trying to read %d bytes of public key part from NV\n", keyBlob.pub.size); - rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, - pubAreaBuffer, &readSize, offset); - if (rc != 0) goto exit; - printf("Successfully read public key part from NV\n\n"); - offset += readSize; + rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, NULL, 0); + if (rc != 0) goto exit; - /* Necessary for storing the publicArea with the correct encoding */ - rc = TPM2_ParsePublic(&keyBlob.pub, pubAreaBuffer, - (word32)sizeof(pubAreaBuffer), &pubAreaSize); - if (rc != TPM_RC_SUCCESS) { - printf("Decoding of PublicArea failed. Unable to extract correctly.\n"); - goto exit; + printf("NV Read: Attributes 0x%08x\n", nv.attributes); + + if (((nv.attributes & TPMA_NV_TPM_NT) >> 4) & TPM_NT_EXTEND) { + byte digest[TPM_SHA256_DIGEST_SIZE]; + word32 digestLen = (word32)sizeof(digest); + printf("NV Read Extend\n"); + nvExtend = 1; + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, digest, &digestLen, 0); + if (rc == 0) { + printf("\tDigest: %d\n", digestLen); + TPM2_PrintBin(digest, digestLen); } - -#ifdef WOLFTPM_DEBUG_VERBOSE - TPM2_PrintPublicArea(&keyBlob.pub); -#endif } + else { + if (partialRead != PRIVATE_PART_ONLY) { + readSize = sizeof(keyBlob.pub.size); + printf("Trying to read %d bytes of public key size marker\n", readSize); + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, + (byte*)&keyBlob.pub.size, &readSize, 0); + if (rc != 0) { + printf("Was a public key part written? (see nvram/store)\n"); + goto exit; + } + printf("Successfully read public key part from NV\n\n"); + offset += readSize; + + readSize = sizeof(UINT16) + keyBlob.pub.size; /* account for TPM2B size marker */ + printf("Trying to read %d bytes of public key part from NV\n", keyBlob.pub.size); + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, + pubAreaBuffer, &readSize, offset); + if (rc != 0) goto exit; + printf("Successfully read public key part from NV\n\n"); + offset += readSize; + + /* Necessary for storing the publicArea with the correct encoding */ + rc = TPM2_ParsePublic(&keyBlob.pub, pubAreaBuffer, + (word32)sizeof(pubAreaBuffer), &pubAreaSize); + if (rc != TPM_RC_SUCCESS) { + printf("Decoding of PublicArea failed. Unable to extract correctly.\n"); + goto exit; + } - if (partialRead != PUBLIC_PART_ONLY) { - printf("Trying to read size marker of the private key part from NV\n"); - readSize = sizeof(keyBlob.priv.size); - rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, - (byte*)&keyBlob.priv.size, &readSize, offset); - if (rc != 0) { - printf("Was a private key part written? (see nvram/store)\n"); - goto exit; + #ifdef WOLFTPM_DEBUG_VERBOSE + TPM2_PrintPublicArea(&keyBlob.pub); + #endif } - printf("Successfully read size marker from NV\n\n"); - offset += readSize; - readSize = keyBlob.priv.size; - printf("Trying to read %d bytes of private key part from NV\n", readSize); - rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, - (byte*)&keyBlob.priv.buffer, &readSize, offset); - if (rc != 0) goto exit; - printf("Successfully read private key part from NV\n\n"); + if (partialRead != PUBLIC_PART_ONLY) { + printf("Trying to read size marker of the private key part from NV\n"); + readSize = sizeof(keyBlob.priv.size); + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, + (byte*)&keyBlob.priv.size, &readSize, offset); + if (rc != 0) { + printf("Was a private key part written? (see nvram/store)\n"); + goto exit; + } + printf("Successfully read size marker from NV\n\n"); + offset += readSize; + + readSize = keyBlob.priv.size; + printf("Trying to read %d bytes of private key part from NV\n", readSize); + rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, + (byte*)&keyBlob.priv.buffer, &readSize, offset); + if (rc != 0) goto exit; + printf("Successfully read private key part from NV\n\n"); + } } /* auth 0 is owner, no auth */ wolfTPM2_SetAuthPassword(&dev, 0, NULL); wolfTPM2_UnsetAuth(&dev, 1); - parent.hndl = authHandle; - rc = wolfTPM2_NVDeleteAuth(&dev, &parent, nvIndex); - if (rc != 0) goto exit; + if (deleteKey) { + parent.hndl = authHandle; + rc = wolfTPM2_NVDeleteAuth(&dev, &parent, nvIndex); + if (rc != 0) goto exit; + } printf("Extraction of key from NVRAM at index 0x%x succeeded\n", nvIndex); - if (!partialRead) { + if (!nvExtend && !partialRead) { /* get SRK */ rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); if (rc != 0) goto exit; diff --git a/examples/nvram/store.c b/examples/nvram/store.c index 7ef611d7..e0657163 100644 --- a/examples/nvram/store.c +++ b/examples/nvram/store.c @@ -50,13 +50,14 @@ static void usage(void) { printf("Expected usage:\n"); - printf("./examples/nvram/store [filename] [-nvindex] [-priv] [-pub] [-aes/-xor]\n"); - printf("* filename: point to a file containing a TPM key\n"); + printf("./examples/nvram/store [filename] [-nvindex] [-priv] [-pub] [-aes/-xor] [-extend]\n"); + printf("* filename: point to a file containing a TPM key (default keyblob.bin\n"); printf("\tDefault filename is \"keyblob.bin\"\n"); printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_NVRAM_STORE_INDEX); printf("* -priv: Store only the private part of the key\n"); printf("* -pub: Store only the public part of the key\n"); printf("* -aes/xor: Use Parameter Encryption\n"); + printf("* -extend: Set TPM_NT_EXTEND\n"); } int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) @@ -80,6 +81,7 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) byte* auth = (byte*)gNvAuth; word32 authSz = (word32)sizeof(gNvAuth)-1; word32 nvSize; + int nvExtend = 0; if (argc >= 2) { if (XSTRCMP(argv[1], "-?") == 0 || @@ -88,9 +90,6 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) usage(); return 0; } - if (argv[1][0] != '-') { - filename = argv[1]; - } } while (argc > 1) { if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) { @@ -124,7 +123,13 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-pub") == 0) { partialStore = PUBLIC_PART_ONLY; } - else if (argv[argc-1][0] == '-') { + else if (XSTRCMP(argv[argc-1], "-extend") == 0) { + nvExtend = 1; + } + else if (argv[argc-1][0] != '-') { + filename = argv[argc-1]; + } + else { printf("Warning: Unrecognized option: %s\n", argv[argc-1]); } argc--; @@ -164,18 +169,25 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) 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 = authHandle; rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes); if (rc != 0) goto exit; - /* Estimate size of NV */ - nvSize = - keyBlob.pub.size + sizeof(keyBlob.pub.size) + sizeof(UINT16) + - keyBlob.priv.size + sizeof(keyBlob.priv.size) + sizeof(UINT16); + if (nvExtend) { + /* set NV type as extend */ + nvAttributes |= (TPMA_NV_TPM_NT & (TPM_NT_EXTEND << 4)); + nvSize = TPM2_GetHashDigestSize(WOLFTPM2_WRAP_DIGEST); + } + else { + rc = readKeyBlob(filename, &keyBlob); + if (rc != 0) goto exit; + + /* Get maximum size of NV */ + nvSize = + keyBlob.pub.size + sizeof(keyBlob.pub.size) + sizeof(UINT16) + + keyBlob.priv.size + sizeof(keyBlob.priv.size) + sizeof(UINT16); + } /* Try and open existing NV */ rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, auth, authSz); @@ -190,53 +202,67 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[]) * as example for how to set the authentication on a handle */ wolfTPM2_SetAuthHandle(&dev, 0, &nv.handle); - printf("Storing key at TPM NV index 0x%x with password protection\n\n", - nvIndex); + if (nvExtend) { + byte* buf = NULL; + size_t bufLen = 0; + printf("Extending TPM NV index 0x%x with file %s\n", + nvIndex, filename); - if (partialStore != PRIVATE_PART_ONLY) { - printf("Public part = %hu bytes\n", keyBlob.pub.size); - rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, - (byte*)&keyBlob.pub.size, sizeof(keyBlob.pub.size), 0); - if (rc != 0) goto exit; - printf("Stored 2-byte size marker before the private part\n"); - offset += sizeof(keyBlob.pub.size); - - /* Necessary for storing the publicArea with the correct byte encoding */ - rc = TPM2_AppendPublic(pubAreaBuffer, (word32)sizeof(pubAreaBuffer), - &pubAreaSize, &keyBlob.pub); - /* Note: - * Public Area is the only part of a TPM key that can be stored encoded - * Private Area is stored as-is, because TPM2B_PRIVATE is byte buffer - * and UINT16 size field, while Public Area is a complex TCG structure. - */ - if (rc != TPM_RC_SUCCESS) { - printf("Encoding of the publicArea failed. Unable to store.\n"); - goto exit; + rc = loadFile(filename, &buf, &bufLen); + if (rc == 0) { + rc = wolfTPM2_NVExtend(&dev, &nv, nvIndex, buf, (word32)bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } + } + else { + printf("Storing key at TPM NV index 0x%x with password protection\n\n", + nvIndex); - /* The buffer holds pub.publicArea and also pub.size(UINT16) */ - rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, - pubAreaBuffer, sizeof(UINT16) + keyBlob.pub.size, offset); - if (rc != 0) goto exit; - printf("NV write of public part succeeded\n\n"); - offset += sizeof(UINT16) + keyBlob.pub.size; + if (partialStore != PRIVATE_PART_ONLY) { + printf("Public part = %hu bytes\n", keyBlob.pub.size); + rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, + (byte*)&keyBlob.pub.size, sizeof(keyBlob.pub.size), 0); + if (rc != 0) goto exit; + printf("Stored 2-byte size marker before the private part\n"); + offset += sizeof(keyBlob.pub.size); + + /* Necessary for storing the publicArea with the correct byte encoding */ + rc = TPM2_AppendPublic(pubAreaBuffer, (word32)sizeof(pubAreaBuffer), + &pubAreaSize, &keyBlob.pub); + /* Note: + * Public Area is the only part of a TPM key that can be stored encoded + * Private Area is stored as-is, because TPM2B_PRIVATE is byte buffer + * and UINT16 size field, while Public Area is a complex TCG structure. + */ + if (rc != TPM_RC_SUCCESS) { + printf("Encoding of the publicArea failed. Unable to store.\n"); + goto exit; + } -#ifdef WOLFTPM_DEBUG_VERBOSE - TPM2_PrintPublicArea(&keyBlob.pub); -#endif - } - if (partialStore != PUBLIC_PART_ONLY) { - printf("Private part = %d bytes\n", keyBlob.priv.size); - rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, - (byte*)&keyBlob.priv.size, sizeof(keyBlob.priv.size), offset); - if (rc != 0) goto exit; - printf("Stored 2-byte size marker before the private part\n"); - offset += sizeof(keyBlob.priv.size); + /* The buffer holds pub.publicArea and also pub.size(UINT16) */ + rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, + pubAreaBuffer, sizeof(UINT16) + keyBlob.pub.size, offset); + if (rc != 0) goto exit; + printf("NV write of public part succeeded\n\n"); + offset += sizeof(UINT16) + keyBlob.pub.size; - rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, - keyBlob.priv.buffer, keyBlob.priv.size, offset); - if (rc != 0) goto exit; - printf("NV write of private part succeeded\n\n"); + #ifdef WOLFTPM_DEBUG_VERBOSE + TPM2_PrintPublicArea(&keyBlob.pub); + #endif + } + if (partialStore != PUBLIC_PART_ONLY) { + printf("Private part = %d bytes\n", keyBlob.priv.size); + rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, + (byte*)&keyBlob.priv.size, sizeof(keyBlob.priv.size), offset); + if (rc != 0) goto exit; + printf("Stored 2-byte size marker before the private part\n"); + offset += sizeof(keyBlob.priv.size); + + rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex, + keyBlob.priv.buffer, keyBlob.priv.size, offset); + if (rc != 0) goto exit; + printf("NV write of private part succeeded\n\n"); + } } exit: diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 3f706a91..96823022 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -257,8 +257,8 @@ if [ $NO_FILESYSTEM -eq 0 ]; then if [ $WOLFCRYPT_ENABLE -eq 1 ]; then ./examples/nvram/store -xor >> run.out 2>&1 RESULT=$? - [ $RESULT -ne 0 ] && echo -e "nv store param enc xorfailed! $RESULT" && exit 1 - ./examples/nvram/read -xor >> run.out 2>&1 + [ $RESULT -ne 0 ] && echo -e "nv store param enc xor failed! $RESULT" && exit 1 + ./examples/nvram/read -xor -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read param enc xor failed! $RESULT" && exit 1 @@ -266,7 +266,7 @@ if [ $NO_FILESYSTEM -eq 0 ]; then ./examples/nvram/store -aes >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv store param enc aes failed! $RESULT" && exit 1 - ./examples/nvram/read -aes >> run.out 2>&1 + ./examples/nvram/read -aes -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read param enc aes failed! $RESULT" && exit 1 fi @@ -274,14 +274,14 @@ if [ $NO_FILESYSTEM -eq 0 ]; then ./examples/nvram/store -priv >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv store priv only failed! $RESULT" && exit 1 - ./examples/nvram/read -priv >> run.out 2>&1 + ./examples/nvram/read -priv -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read priv only failed! $RESULT" && exit 1 if [ $WOLFCRYPT_ENABLE -eq 1 ]; then ./examples/nvram/store -priv -xor >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv store priv only param enc xor failed! $RESULT" && exit 1 - ./examples/nvram/read -priv -xor >> run.out 2>&1 + ./examples/nvram/read -priv -xor -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read priv only param enc xor failed! $RESULT" && exit 1 @@ -289,7 +289,7 @@ if [ $NO_FILESYSTEM -eq 0 ]; then ./examples/nvram/store -priv -aes >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv store priv only param enc aes failed! $RESULT" && exit 1 - ./examples/nvram/read -priv -aes >> run.out 2>&1 + ./examples/nvram/read -priv -aes -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read priv only param enc aes failed! $RESULT" && exit 1 fi @@ -297,9 +297,33 @@ if [ $NO_FILESYSTEM -eq 0 ]; then ./examples/nvram/store -pub >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv store pub only failed! $RESULT" && exit 1 - ./examples/nvram/read -pub >> run.out 2>&1 + ./examples/nvram/read -pub -delete >> run.out 2>&1 RESULT=$? [ $RESULT -ne 0 ] && echo -e "nv read pub only failed! $RESULT" && exit 1 + + # extend tests + ./examples/nvram/store -nvindex=0x01800203 -extend + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend failed! $RESULT" && exit 1 + ./examples/nvram/read -nvindex=0x01800203 -delete + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend read failed! $RESULT" && exit 1 + + if [ $WOLFCRYPT_ENABLE -eq 1 ]; then + ./examples/nvram/store -nvindex=0x01800203 -extend -xor + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend xor failed! $RESULT" && exit 1 + ./examples/nvram/read -nvindex=0x01800203 -xor -delete + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend read xor failed! $RESULT" && exit 1 + + ./examples/nvram/store -nvindex=0x01800203 -aes -extend + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend aes failed! $RESULT" && exit 1 + ./examples/nvram/read -nvindex=0x01800203 -aes -delete + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "nv extend read aes failed! $RESULT" && exit 1 + fi fi ./examples/nvram/policy_nv >> run.out 2>&1 diff --git a/src/tpm2.c b/src/tpm2.c index 955cdfe0..9984ee70 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -5056,6 +5056,9 @@ TPM_RC TPM2_NV_Extend(NV_Extend_In* in) TPM2_Packet_Init(ctx, &packet); TPM2_Packet_AppendU32(&packet, in->authHandle); + /* When using an HMAC or Policy session make sure the NV "name" is + * populated in the TPM2_AUTH_SESSION name.name. This is a computed + * hash (see TPM2_HashNvPublic) */ TPM2_Packet_AppendU32(&packet, in->nvIndex); TPM2_Packet_AppendAuth(&packet, ctx, &info); diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 969e1973..a007774a 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -4498,13 +4498,16 @@ int wolfTPM2_NVCreate(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, maxSize, auth, authSz); } -int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, +static 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 nvIndex, byte* dataBuf, word32 dataSz, word32 offset, int extend) { int rc = TPM_RC_SUCCESS; word32 pos = 0, towrite; - NV_Write_In in; + union { + NV_Write_In write; + NV_Extend_In extend; + } in; if (dev == NULL || nv == NULL || dataBuf == NULL) { return BAD_FUNC_ARG; @@ -4541,29 +4544,34 @@ int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, rc |= wolfTPM2_SetAuthHandleName(dev, 1, &nv->handle); if (rc != TPM_RC_SUCCESS) { #ifdef DEBUG_WOLFTPM - printf("Setting NV index name failed\n"); + printf("wolfTPM2_NVWriteData: Setting NV index name failed\n"); #endif rc = TPM_RC_FAILURE; break; } XMEMSET(&in, 0, sizeof(in)); - in.authHandle = nv->handle.hndl; - in.nvIndex = nvIndex; - in.offset = offset+pos; - in.data.size = towrite; + in.write.authHandle = nv->handle.hndl; + in.write.nvIndex = nvIndex; + in.write.data.size = towrite; if (dataBuf) - XMEMCPY(in.data.buffer, &dataBuf[pos], towrite); - - rc = TPM2_NV_Write(&in); + XMEMCPY(in.write.data.buffer, &dataBuf[pos], towrite); + if (!extend) { + in.write.offset = offset+pos; + rc = TPM2_NV_Write(&in.write); + } + else { + rc = TPM2_NV_Extend(&in.extend); + } if (rc != TPM_RC_SUCCESS) { break; } #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); + 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); #endif pos += towrite; @@ -4572,18 +4580,34 @@ int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* tpmSession, #ifdef DEBUG_WOLFTPM if (rc != TPM_RC_SUCCESS) { - printf("TPM2_NV_Write failed %d: %s\n", rc, wolfTPM2_GetRCString(rc)); + printf("wolfTPM2_NVWriteData failed %d: %s\n", + rc, wolfTPM2_GetRCString(rc)); } #endif return rc; } +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); +} + +int wolfTPM2_NVWriteAuthPolicy(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) +{ + return wolfTPM2_NVWriteData(dev, tpmSession, pcrAlg, pcrArray, pcrArraySz, + nv, nvIndex, dataBuf, dataSz, offset, 0); +} + int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset) { - return wolfTPM2_NVWriteAuthPolicy(dev, NULL, TPM_ALG_NULL, NULL, 0, - nv, nvIndex, dataBuf, dataSz, offset); + return wolfTPM2_NVWriteData(dev, NULL, TPM_ALG_NULL, NULL, 0, + nv, nvIndex, dataBuf, dataSz, offset, 0); } /* older API kept for compatibility, recommend using wolfTPM2_NVWriteAuth */ @@ -4789,6 +4813,7 @@ int wolfTPM2_NVOpen(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, word32 nvIndex, /* flag that the NV was "opened" and name was loaded */ nv->handle.nameLoaded = 1; + nv->attributes = nvPublic.attributes; return rc; } diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index d72e8c44..02bc14b9 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -1552,7 +1552,7 @@ typedef UINT32 TPMA_NV; #define TPMA_NV_OWNERWRITE 0x00000002UL #define TPMA_NV_AUTHWRITE 0x00000004UL #define TPMA_NV_POLICYWRITE 0x00000008UL -#define TPMA_NV_TPM_NT 0x000000F0UL +#define TPMA_NV_TPM_NT 0x000000F0UL /* index type see TPM_NT_ */ #define TPMA_NV_POLICY_DELETE 0x00000400UL #define TPMA_NV_WRITELOCKED 0x00000800UL #define TPMA_NV_WRITEALL 0x00001000UL diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 4932b58f..61d10494 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -92,6 +92,7 @@ typedef struct WOLFTPM2_HASH { typedef struct WOLFTPM2_NV { WOLFTPM2_HANDLE handle; + TPMA_NV attributes; } WOLFTPM2_NV; typedef struct WOLFTPM2_HMAC { @@ -2014,6 +2015,29 @@ WOLFTPM_API int wolfTPM2_NVWriteAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, WOLFTPM2_NV* nv, word32 nvIndex, byte* dataBuf, word32 dataSz, word32 offset); +/*! + \ingroup wolfTPM2_Wrappers + \brief Extend data to an NV index + \note When NV index is read it will return the digest + + \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 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 + + \sa wolfTPM2_NVReadAuth + \sa wolfTPM2_NVCreateAuth + \sa wolfTPM2_NVOpen + \sa wolfTPM2_NVDeleteAuth +*/ +WOLFTPM_API int wolfTPM2_NVExtend(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, + word32 nvIndex, byte* dataBuf, word32 dataSz); + /*! \ingroup wolfTPM2_Wrappers \brief Reads user data from a NV Index, starting at the given offset