Created
April 16, 2020 17:02
-
-
Save williamcroberts/e08c7a99fa7a66be7c30bd62e38d4e24 to your computer and use it in GitHub Desktop.
An Example of creating, writing, reading and deleting a TPM2.0 NV Index using the ESAPI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <tss2/tss2_esys.h> | |
#include <tss2/tss2_rc.h> | |
#define DATA "hello world" | |
int main(int argc, char *argv[]) { | |
ESYS_CONTEXT *ectx = NULL; | |
ESYS_TR nv_index = 0; | |
ESYS_TR nv_index2 = 0; | |
int rc = 1; | |
/* | |
* create a connection to the TPM letting ESAPI choose how to get there. | |
* If you need more control, you can use tcti and tcti-ldr libraries to | |
* get a TCTI pointer to use for the tcti argument of Esys_Initialize. | |
*/ | |
rc = Esys_Initialize(&ectx, | |
NULL, /* let it find the TCTI */ | |
NULL);/* Use whatever ABI */ | |
if (rc != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_Initialize: 0x%x\n", rc); | |
return 1; | |
} | |
/* build a template for the NV index */ | |
TPM2B_NV_PUBLIC pub_templ = { | |
/* this is counter intuitive, but it tells the TSS2 library to calculate this for us */ | |
.size = 0, | |
/* The things that define what NV index we are creating */ | |
.nvPublic = { | |
/* uses sha256 to identify the tpm object by name */ | |
.nameAlg = TPM2_ALG_SHA256, | |
/* allows the owner password or index password r/w access */ | |
.attributes = TPMA_NV_OWNERWRITE | | |
TPMA_NV_OWNERREAD | | |
TPMA_NV_AUTHWRITE | | |
TPMA_NV_AUTHREAD, | |
/* can hold 64 bytes of data */ | |
.dataSize = 64, | |
/* Create at NV Index 1 or 0x1000001 */ | |
.nvIndex = TPM2_HR_NV_INDEX + 1 | |
}, | |
}; | |
/* Ok, define the space and store the nv_index for future use */ | |
rc = Esys_NV_DefineSpace( | |
ectx, | |
ESYS_TR_RH_OWNER, /* create an NV index in the owner hierarchy */ | |
ESYS_TR_PASSWORD, /* auth as the owner with a password, which is empty */ | |
ESYS_TR_NONE, | |
ESYS_TR_NONE, | |
NULL, | |
&pub_templ, | |
&nv_index); | |
if (rc != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_NV_DefineSpace: 0x%x\n", rc); | |
goto out; | |
} | |
/* Note if you need to set the owner hierarchy auth value you use: | |
* TSS2_RC Esys_TR_SetAuth( | |
* ESYS_CONTEXT *esysContext, | |
* ESYS_TR handle, | |
* TPM2B_AUTH const *authValue); | |
*/ | |
printf("Created NV Index: 0x%x\n", pub_templ.nvPublic.nvIndex); | |
printf("ESYS_TR: 0x%x\n", nv_index); | |
/* | |
* Note: if you need to convert the nvIndex into an ESYS_TR, the below will | |
* do it. Its not required for this case, since Esys_NV_Define gives us an | |
* ESYS_TR. | |
*/ | |
rc = Esys_TR_FromTPMPublic( | |
ectx, | |
TPM2_HR_NV_INDEX + 1, | |
ESYS_TR_NONE, | |
ESYS_TR_NONE, | |
ESYS_TR_NONE, | |
&nv_index2); | |
if (rc != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_TR_FromTPMPublic: 0x%x\n", rc); | |
goto out; | |
} | |
printf("ESYS_TR2: 0x%x\n", nv_index2); | |
/* copy some data into a buffer to send to the TPM */ | |
TPM2B_MAX_NV_BUFFER write_data = { 0 }; | |
memcpy(write_data.buffer, DATA, sizeof(DATA)); | |
write_data.size = sizeof(DATA); | |
/* | |
* Write the data to the TPM NV index at offset 0 | |
*/ | |
rc = Esys_NV_Write( | |
ectx, | |
nv_index, /* authenticate to the NV index using the NV index password */ | |
nv_index, /* the nv index to write to */ | |
ESYS_TR_PASSWORD, | |
ESYS_TR_NONE, | |
ESYS_TR_NONE, | |
&write_data, | |
0); | |
if (rc != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_NV_Write: 0x%x\n", rc); | |
goto out; | |
} | |
/* Read the data back, and just for fun, we will use nv_index2 | |
* to prove it's pointing to the same NV location in the TPM. | |
*/ | |
TPM2B_MAX_NV_BUFFER *read_data = NULL; | |
rc = Esys_NV_Read( | |
ectx, | |
nv_index2, /* authenticate to the NV index using the NV index password */ | |
nv_index2, /* the nv index to read from */ | |
ESYS_TR_PASSWORD, | |
ESYS_TR_NONE, | |
ESYS_TR_NONE, | |
sizeof(DATA), | |
0, | |
&read_data); | |
if (rc != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_NV_Read: 0x%x\n", rc); | |
goto out; | |
} | |
/* Print things as a string from the TPM carefully! | |
* Injected traffic via MITM means that you cannot trust this | |
* to be null terminated. | |
*/ | |
printf("%.*s\n", read_data->size, read_data->buffer); | |
Esys_Free(read_data); | |
printf("Their is a lot more to make this better, like encrypted sessions with the\n" | |
"TPM so you cannot be MITM attacked. As well as dealing with authorizations\n" | |
"like passwords and policies to access the owner hiearchy and nv index values.\n"); | |
/* success, yeah :-) */ | |
rc = 0; | |
out: | |
/* remove the NV space */ | |
if (nv_index) { | |
int rc2 = Esys_NV_UndefineSpace( | |
ectx, | |
ESYS_TR_RH_OWNER, | |
nv_index, | |
ESYS_TR_PASSWORD, | |
ESYS_TR_NONE, | |
ESYS_TR_NONE); | |
if (rc2 != TSS2_RC_SUCCESS) { | |
fprintf(stderr, "Esys_NV_UndefineSpace: 0x%x\n", rc2); | |
rc = 1; | |
} | |
} | |
Esys_Finalize(&ectx); | |
return rc; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment