NVRAM Write and Read using Esys API(s)
by muthu.smk@gmail.com
Hi Williams,
I am using the test code used to read and write in to NV ram. I am facing below challenges if i tried to read already written data from NVRAM.
1) Test code attached defined create the context (ectx) , create random number , define NV ram , write the random number in to NVRAM (offset 0x1000001) and read it back from NV Ram (from same offset 0x1000001)
2) But if i try to run this code twice or thrise , am getting below NVRAM already defined rc code. I can understand that we should not defined the nv ram space which already defined and used.
How to avoid this ? by defining nvram ONLY once and write it ONLY once and finally read it AS MUCH times we want ? Below details are related to this request
Error code:
0x0000014c - description: NV Index or persistend object already defined
0x00000284 - description: value is out of range or is not correct for the context
3) Query is : is it possible to define nvram "ONLY ONCE" with the API shared the test code
and then create a function "createrandom" number to use the same context (ects) to generate randumnumber
then call separate "write_nvram" function with random number as input and ask to write in the same offset . Finally calling another function "read_nvram" to read it back from the same nvram's offset when ever we want ? i tried this approach but am getting segfault with above error .
What am i missing here ?
3.1) Ideally in single application , i need to achieve "tpm2_nvdefine", "tpm2_nvwrite" and "tpm2_nvread() tools API(s) functionality" in different calls or flow.
3.2) Also how to check whether "write" already done (i tried checking nv_index is true - means whether it already has some value) , but it failed ?
4) Also how to check what was the content that already present in the nvram offset (0x1000001) before i do write the "random number" second time in to the same offset ? this is to ensure the "random number" that i am planning to write was valid one ?
I remember studying that, once u write in to NVRAM offset , we cant able to RE-WRITE it in the same offset(0x1000001). Whether that is the same case for SIMULATOR as well (or) this feature is only for real tpm hardware?
6)After nvwrite i tried to use "tpm2_pcrlist" command line tool application, by which it shows the nv ram memory location , tried using tpm2_nvread () to read the content but i could not able to see any data (random number) that i used to write via this test application . dont know why ?
7) After i manually ran the below clear API , now the test code is working fine (refer Test code log shown below..). This confirms we can reallocate already defined nv ram memory.
#tpm2_nvrelease -x 0x1000001 -a 0x40000001
8)If i try to read it manually via below tpm2_nvread command with offset 0x1000001 am getting below error
#tpm2_nvread -x 0x1000001 -a 0x40000001 -o 0 -s 20
ERROR: Failed to read NVRAM public area at index 0x1000001 (16777217). Error:0x18b
ERROR: Unable to run tpm2_nvread
/* Tried to use below tools command , am always getting the same error even if we give the different nvram off set
tpm2_nvwrite -x 0x1c00002 helloworld
ERROR: Reading the public part of the nv index failed with: 0x18b
ERROR: Unable to run tpm2_nvwrite
tpm2_nvwrite -x 0x1c00012 -a 0x40000001 helloworld
ERROR: Reading the public part of the nv index failed with: 0x18b
ERROR: Unable to run tpm2_nvwrite
/* Try to read the nvlist of SIM , it returns nothing !!!
#tpm2_nvlist <returns nothing>
Any points will be great help for me.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Test code log after above "tpm2_nvrelease":
Initializing
init_rand()
init_rsa()
init_ecc()
Engine name: TPM2-TSS engine for OpenSSL
Init result: 1
Setting owner auth to empty auth.
Setting parent auth to empty auth.
ERROR:tcti:src/tss2-tcti/tcti-device.c:440:Tss2_Tcti_Device_Init() Failed to open device file /dev/tpm0: No such file or directory
WARNING:tcti:src/tss2-tcti/tctildr.c:62:tcti_from_init() TCTI init for function 0x7fc67376d18b failed with a000a
WARNING:tcti:src/tss2-tcti/tctildr.c:92:tcti_from_info() Could not initialize TCTI named: tcti-device
ERROR:tcti:src/tss2-tcti/tctildr-dl.c:150:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-default.so
No of bytes written by GenRandom : 64
b6c9e1d028f2c893c56a089165f9f38c09232180ba5bb66b35c5652cb51ab61b237ecfe8ece5d7f14a3323fee1dca0e641a0f20c7689100e3c804b82d6a2497f
Created NV Index: 0x1000001
ESYS_TR: 0x418367
ESYS_TR2: 0x418368
Writing the random number written in NV Ram
Data buffer size used to write into NVRam: 64
Reading the random number written in NV Ram
b6c9e1d028f2c893c56a089165f9f38c09232180ba5bb66b35c5652cb51ab61b237ecfe8ece5d7f14a3323fee1dca0e641a0f20c7689100e3c804b82d6a2497f
*** SUCCESS ***
---------------------
TEST CODE :
int nv_write_read()
{
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) {
printf("Esys_Initialize Failed: 0x%x\n", rc);
return 1;
}
rc = Esys_GetRandom(ectx,
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
64, &bytes);
if (rc != TSS2_RC_SUCCESS) {
printf("Esys_GetRandom Failed: %s\n", Tss2_RC_Decode(rc));
exit(1);
}
printf(" No of bytes written by GenRandom : %d\n",bytes->size);
size_t i;
for (i = 0; i < bytes->size; i++) {
printf("%02x", bytes->buffer[i]);
}
printf("\n");
/* 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) {
printf("Esys_NV_DefineSpace Failed: 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 we 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) {
printf("Esys_TR_FromTPMPublic Failed: 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, bytes->buffer, bytes->size);
write_data.size = bytes->size;
printf("Writing the random number written in NV Ram\n");
printf("Data buffer size used to write into NVRam: %d\n",write_data.size);
/*
* 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) {
printf("Esys_NV_Write Failed: 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,
bytes->size,
0,
&read_data);
if (rc != TSS2_RC_SUCCESS) {
printf("Esys_NV_Read Failed: 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("Reading the random number written in NV Ram\n");
for (i = 0; i < read_data->size; i++) {
printf("%02x", read_data->buffer[i]);
}
printf("\n");
Esys_Free(read_data);
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) {
printf("Esys_NV_UndefineSpace Failed: 0x%x\n", rc2);
rc = 1;
}
}
Esys_Finalize(&ectx);
printf("Exit from nv_write_read()\n");
return rc;
}
2 years, 2 months
The script of make credential met error
by Zhao, Shirley
Hi, all,
Met the following error when running make credential script as below:
$ tpm2_createek -c 0x81010009 -G rsa -u ek.pub --tcti=mssim
$ tpm2_getcap handles-persistent --tcti=mssim
- 0x81010009
$ tpm2_getcap handles-transient --tcti=mssim
$ tpm2_createak -C 0x81010009 -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub -n ak.name --tcti=mssim
loaded-key:
name: 000b57d43d757f62362402a6d473f622a28916b8289ef49dc2e52daf13174a2c9e7e
$ tpm2_getcap handles-persistent --tcti=mssim
- 0x81010009
$ tpm2_getcap handles-transient --tcti=mssim
- 0x80000001
$ echo 12345678 > secret.data
$ tpm2_makecredential -e ek.pub -s secret.data -n 000b57d43d757f62362402a6d473f622a28916b8289ef49dc2e52daf13174a2c9e7e -o mkcred.out --tcti=mssim
ERROR:esys:src/tss2-esys/esys_iutil.c:389:iesys_handle_to_tpm_handle() Error: Esys invalid ESAPI handle (40000007).
ERROR:esys:src/tss2-esys/api/Esys_LoadExternal.c:85:Esys_LoadExternal() Error in async function ErrorCode (0x0007000b)
ERROR: Esys_LoadExternal(0x7000B) - esapi:A parameter has a bad value
ERROR: Unable to run tpm2_makecredential
The script is from tpm2-tools/test/integration/tests/Activecredential.sh.
Please help check.
Thanks.
- Shirley
2 years, 2 months
The script of evictcontrol failed during create ek and ak
by Zhao, Shirley
Thanks, Imran.
I have fixed the failure of the script of tpm2_policyauthorize.
Now, I met another failure when running the script on https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_createak....
The log is:
$ tpm2_startup --clear --tcti=mssim
$ tpm2_createek -c ek.handle -G rsa -u ek.pub --tcti=mssim
$ tpm2_createak -C ek.handle -c ak.ctx -u ak.pub -n ak.name --tcti=mssim
loaded-key:
name: 000ba3f7e942e3d87b2c7bebb28f6893c4146bc5a89a4018c9f6b778406f2eac0fea
$ tpm2_evictcontrol -C o -c ak.ctx 0x81010002 --tcti=mssim
WARNING:esys:src/tss2-esys/api/Esys_ContextLoad.c:279:Esys_ContextLoad_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_ContextLoad.c:93:Esys_ContextLoad() Esys Finish ErrorCode (0x00000902)
ERROR: Esys_ContextLoad(0x902) - tpm:warn(2.0): out of memory for object contexts
ERROR:esys:src/tss2-esys/esys_tr.c:357:Esys_TR_Close() Error: Esys handle does not exist (70018).
ERROR: Esys_TR_Close(0x70018) - esapi:The ESYS_TR resource object is bad
ERROR: Unable to run tpm2_evictcontrol
Not sure whether it is the handle is wrong, because when check transient handle as below.
$ tpm2_getcap handles-transient --tcti=mssim
- 0x80000000
- 0x80000001
- 0x80000002
But even I update the 0x81010002 into 0x80000000, 0x80000001 or 0x80000002, it still result in the same error.
Please help, thanks.
* Shirley
From: Zhao, Shirley
Sent: Monday, April 27, 2020 5:33 PM
To: 'tpm2(a)lists.01.org' <tpm2(a)lists.01.org>
Subject: The script of tpm2_policyauthorize failed
Hi, all,
I ran the script of tpm2_policyauthorize and met error.
The steps is following the page https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_policyau....
Not sure whether it is the script error or any bug in source code.
The log is as below, please help check.
$ openssl genrsa -out signing_key_private.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
........................+++++
....................................................................................................................................................................................................................................+++++
e is 65537 (0x010001)
$ openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout
writing RSA key
$ tpm2_startup --clear --tcti=mssim
$ tpm2_loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx -n signing_key.name --tcti=mssim
name: 000be282af94009998a545488daf129bac7379048a44361b9e77df40a03bc4ab8a4e
$ tpm2_pcrread -opcr0.sha256 sha256:0 --tcti=mssim
sha256:
0 : 0x0000000000000000000000000000000000000000000000000000000000000000
$ tpm2_startauthsession -S session.ctx --tcti=mssim
$ tpm2_policypcr -S session.ctx -l sha256:0 -f pcr0.sha256 -L pcr.policy --tcti=mssim
093ceb41181d47808862d7946268ee6a17a10e3d1b79b32351bc56e4beaceff0
$ tpm2_flushcontext session.ctx --tcti=mssim
$ openssl dgst -sha256 -sign signing_key_private.pem -out pcr.signature pcr.policy
$ tpm2_startauthsession -S session.ctx --tcti=mssim
$ tpm2_policyauthorize -S session.ctx -L authorized.policy -i pcr.policy -n signing_key.name --tcti=mssim
1307183d719d482ddb2465b67e31ee1728313157d4be0f15a6fe0ded4540758d
$ tpm2_flushcontext session.ctx --tcti=mssim
$ tpm2_nvdefine 0x1500017 -C o -s 32 -L authorized.policy -a "policyread|policywrite" --tcti=mssim
nv-index: 0x1500017
$ tpm2_verifysignature -c signing_key.ctx -g sha256 -m pcr.policy -s pcr.signature -t verification.tkt -f rsassa --tcti=mssim
$ tpm2_startauthsession --policy-session -S session.ctx --tcti=mssim
$ tpm2_policyauthorize -S session.ctx -L authorized.policy -i pcr.policy -n signing_key.name -t verification.tkt --tcti=mssim
WARNING:esys:src/tss2-esys/api/Esys_PolicyAuthorize.c:306:Esys_PolicyAuthorize_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_PolicyAuthorize.c:108:Esys_PolicyAuthorize() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_PolicyAuthorize(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Could not build tpm authorized policy
ERROR: Unable to run tpm2_policyauthorize
$ echo "nvpolicyauthorizetest" > nv.test_w
$ tpm2_nvwrite 0x1500017 -P"session:session.ctx" -i nv.test_w --tcti=mssim
WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:310:Esys_NV_Write_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x0000099d)
ERROR: Failed to write NV area at index 0x1500017
ERROR: Tss2_Sys_NV_Write(0x99D) - tpm:session(1):a policy check failed
ERROR: Unable to run tpm2_nvwrite
Thanks.
* Shirley
2 years, 2 months
compile error on tpm2-tools (4.2.X branch)
by ted.h.kim@oracle.com
Folks,
I got an "error" compiling tpm2-tools (4.2.X branch).
Yes, I realize this is because warnings being converted to errors.
Don't think I changed the CC flags, but maybe this is just my environment?
Haven't checked the new 4.2.1 release update - does that take care of this?
Thanks,
-ted
++++
from the make output:
lib/tpm2.c: In function ‘tpm2_getsapicontext’:
lib/tpm2.c:4070:20: error: implicit declaration of function
‘Esys_GetSysContext’
; did you mean ‘Esys_FlushContext’? [-Werror=implicit-function-declaration]
TSS2_RC rval = Esys_GetSysContext(esys_context, sys_context);
^~~~~~~~~~~~~~~~~~
Esys_FlushContext
cc1: all warnings being treated as errors
make: *** [Makefile:4857: lib/libcommon_a-tpm2.o] Error 1
--
Ted H. Kim, PhD
ted.h.kim(a)oracle.com
+1 310-258-7515
2 years, 2 months
default TCTI name - how to compile the default as tabrmd
by ted.h.kim@oracle.com
Folks,
After I built the tools, I found that the default TCTI was device rather
than the tabrmd.
# tpm2_getcap -v
tool="tpm2_getcap" version="4.1.2-rc0" tctis="libtss2-tctildr"
tcti-default=tcti-device
But what I think I want is that the tcti-default=tabrmd.
I know about the -T option and the TPM2TOOLS_TCTI environment variable.
But can I just compile it to have it default to tabrmd?
Is this some "configure" option or something?
How do I change how it compiles?
Thanks,
-ted
--
Ted H. Kim, PhD
ted.h.kim(a)oracle.com
+1 310-258-7515
2 years, 2 months
Re: Hello from a small community of TPM enthusiasts
by Roberts, William C
> -----Original Message-----
> From: Dimitar Tomov [mailto:dimi@designfirst.ee]
> Sent: Thursday, May 7, 2020 5:46 AM
> To: David Woodhouse <dwmw2(a)infradead.org>; tpm2(a)lists.01.org
> Subject: [tpm2] Re: Hello from a small community of TPM enthusiasts
>
> Hi David,
>
> May be outdated, but your page is also a resource, so please feel free to share it
> with the community developers.tpm.dev ;-)
>
> For the other topics you rise I will reply inline below
>
> On Wed, 2020-05-07 at 13:16, David Woodhouse wrote:
> > I'll see if I can join.
>
> We are doing them every week, so even if you miss next week's call, just join us
> in next one. Same time, Wednesday 8am PDT/5pm CEST
>
> >
> > With respect to documentation I'd strongly recommend taking the
> > approach of "if it needs documenting, fix it first. Then document
> > what's left".
>
> I could not agree more. We are not the ones developing tpm2-tools, rather trying
> to make use of them. But we can provide valuable feedback.
>
> > We should make software as trivial and intuitive as possible for
> > users, not *just* provide a twisty maze of documentation in the hope
> > that some of the most persistent will eventually navigate their way through it.
>
> Spot on. I have one such example from yesterday, where we were wondering
> why generating a symmetric key with tpm2-tools now produces private and
> public part. Eventually, a clean slide would be the only viable option left. I
> personally am a fan of the minimalistic approach.
> We can discuss this further on our calls. I do not want to go offtopic here.
>
Why "now produces"tpm2_create has always produced a public and private portion.
Did something change that I am not aware of?
As Andreas mentioned, those blobs are for the TPM, and contain a lot of metadata outside
Of what one typically things of as a public portion of a key. For example RSA would contain
At a minimum the exponent and the modulus. The public portion of a tpm file contains
attributes and for a symmetric key, which can be viewed with tpm2_readpublic, and
some of them are output on tpm2_create as well (stdout output).
$ tpm2_readpublic -c aes.key
name: 000b530cfa588448c802f23b06707ae1a140fec0d5b2d4dfc6de114094f4cbca8b9b
qualified name: 000ba07ee113cee302967a859956e4351b966d3216a3949702e919248c354876d432
name-alg:
value: sha256
raw: 0xb
attributes:
value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign
raw: 0x60072
type:
value: symcipher
raw: 0x25
sym-alg:
value: aes
raw: 0x6
sym-mode:
value: null
raw: 0x10
sym-keybits: 256
symcipher: b916f79cc7984287fee3632df1dbf061594e01c4c01401f379a8e08867bfee7a
All those fields have meaning, for instance that name of the object, is the hash of type sha256.
Names are unique, and how we make sure we're getting what we expect when using them for
Things like encrypted sessions.
The attributes describe how that object can be used, it can't be reparented within the TPM, its fixed to the TPM
And cannot be extracted, and is authorized by the user with a password. It can be used for both encryption (sign)
and decryption.
Type, syme-alg and sym-mode all describe the associated algorithm of the object, it's a symmetric cipher of type
AES and since mode is null, it can be used with any supported AES mode, ie CBC, ECB, etc. You could set this to
a single mode at tpm2_create time, and then the key would be restricted to a single mode.
It tells you the keybits, and the symcipher field is a fingerprint of the key. For AES offhand I think it's the name-alg
Hash (sha256) of the key bytes. For RSA this would be the modulus, and the field name would be rsa. Rsa would also
Contain the exponent, so you could actual use it like a public key. In fact readpublic can output the public
as a pem for asymmetric keypairs.
Additionally, the public and private are bound cryptograhically, so the TPM knows what public corresponds with the
private key (in this case the AES secret key) and thus can trust the public portion in making policy decisions, like
don't allow it to be reparented or be extracted from the TPM.
The private portion is encrypted and integrity checked by the TPM, so (hopefully) only the TPM can view the actual
key material.
Hopefully this helps, we try and distill stuff down in the tpm2-tools manpages the best we can and work on other
Supporting documentation as well. We need to start making things like, diving into objects. Because these details
I just shared are only in the spec....which is not exactly fun to read at times, albeit thorough.
> /Dimi
>
>
> _______________________________________________
> tpm2 mailing list -- tpm2(a)lists.01.org
> To unsubscribe send an email to tpm2-leave(a)lists.01.org
> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
2 years, 2 months