Skip to content

Commit

Permalink
Add support for NV extend.
Browse files Browse the repository at this point in the history
  • Loading branch information
dgarske committed Dec 10, 2024
1 parent d0618ad commit 6f9593e
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 131 deletions.
2 changes: 1 addition & 1 deletion examples/gpio/gpio_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
126 changes: 76 additions & 50 deletions examples/nvram/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[])
Expand All @@ -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 ||
Expand Down Expand Up @@ -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]);
}
Expand Down Expand Up @@ -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;
Expand Down
136 changes: 81 additions & 55 deletions examples/nvram/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[])
Expand All @@ -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 ||
Expand All @@ -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) {
Expand Down Expand Up @@ -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--;
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand Down
Loading

0 comments on commit 6f9593e

Please sign in to comment.