Closed saravanj24 closed 2 years ago
Hi, have a look at that link where I patched u-boot to add a TPM command: https://github.com/joholl/rpi4-uboot-tpm/issues/1#issuecomment-694898768
Please also consider submitting your change upstream ;)
Btw, mainline u-boot already supports NV define/write/read: https://source.denx.de/u-boot/u-boot/-/blob/master/lib/tpm-v2.c
You just cannot read/write with policies or authValues (= passwords). The latter could be added easily if that's what you need.
The below things we tried in the user space for the nvdefine and nv write/read
1.tpm2_nvdefine 0x1500030 -C 0x40000001 -s 10 -a 0x2000A
2.tpm2_nvwrite 0x1500030 -i - < inputdata
3.tpm2_nvread 0x1500030
with the above steps we can able do the read/write succesfully.
We undefine the nvindex created.
We tried the same above mentioned steps in the u-boot.
We created the do_tpm2_nv_define() to get command as the input to define the nv_index.
while executing the do_tpm2_nv_define() --> tpm2_nv_define_space(),it responded with the error
TPM response [ret:725]: 80 01 00 00 00 0a 00 00 02 d5 Error: 725
Queries: 1.Is there any specific nv index we should use in the U-boot? 2.We assigned the owner read/owner write/Policy write in the nv_attributes to define the nv_index? Is there any attributes we need to set? 3.We also tried by setting nv_attributes as owner read/owner write alone, still we are getting same error response as 725. 4.We unable to find the error code details in TPM2.0 source package and also in related docs,suggest where we need to refer this? 5.Is there any other functionalities to be handle to define the nv_index?
Meanwhile we also tried with the which already available in the TPM U-boot package.
we checked with the early_nvram2 command, it failed during nv_write callback with the below error.
U-Boot> tpmtest early_nvram2 argc = 2, argv = tpmtest early_nvram2
Testing earlynavram2...TESTFAILED:line122:tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)): 0x284
Is there any update in the test commands for TPM2.0? is there we need to pass any arguments for this test command? is there any reference document available?
TL;DR: Either your do_tpm2_nv_define()
has a bug or you pass bad values.
I broke the TPM2_NV_DefineSpace
command down to the bytes as an example for you.
header:
.tag: 80 02
.size: 00 00 00 2d
.commandCode: 00 00 01 2a
handle: 40 00 00 0c # platform
authArea:
.size: 00 00 00 09
.sessionHandle: 40 00 00 09 # password session
.nonce: 00 00 # empty (size = 0)
.attributes: 00
.sessionAuth: 00 00 # empty (size = 0)
auth: 00 00
publicInfo:
.size: 00 0e
.nvPublic:
nvPublic.nvIndex: 01 40 00 01 # arbitrary free NV index
nvPublic.nameAlg: 00 04 # SHA1
nvPublic.attributes: 44 04 20 04 # attributes, here TPMA_NV_AUTHREAD | TPMA_NV_POLICYWRITE | TPMA_NV_PLATFORMCREATE
nvPublic.authPolicy: 00 00 # empty policy (size = 0)
nvPublic.dataSize: 00 22 # size of the NV space: 34 bytes
You can verify this by sending these raw bytes to your TPM (or a TPM simulator, here mssim = Microsoft Simulator):
echo "80 02 00 00 00 2d 00 00 01 2a 40 00 00 0c 00 00 00 09 40 00 00 09 00 00 00 00 00 00 00 00 0e 01 40 00 01 00 04 44 04 20 04 00 00 00 22" | xxd -r -p | tpm2_send --tcti="mssim" | xxd -p
We created the do_tpm2_nv_define() to get command as the input to define the nv_index.
There is already an API call for defining an NV space in mainline U-Boot. You might want to use that.
1.Is there any specific nv index we should use in the U-boot?
Have a look at the reserved indices. Just use something in the unassigned range: 0x01000000-0x013FFFFF.
2.We assigned the owner read/owner write/Policy write in the nv_attributes to define the nv_index? Is there any attributes we need to set?
You're basically setting access control options here. That should not impact defining the space. Please refer to the specification for more info.
3.We also tried by setting nv_attributes as owner read/owner write alone, still we are getting same error response as 725.
See above.
4.We unable to find the error code details in TPM2.0 source package and also in related docs,suggest where we need to refer this?
You can use the tpm2-tools
for info about return codes:
$ tpm2 rc_decode 0x02d5
tpm:parameter(2):structure is the wrong size
Basically, that error code is TPM2_RC_P (0x40) | TPM2_RC_SIZE (0x95)
From the TSS definitions:
#define TPM2_RC_FMT1 ((TPM2_RC) 0x080) /* This bit is SET in all format 1 response codes. The codes in this group may have a value added to them to indicate the handle session or parameter to which they apply. */
#define TPM2_RC_P ((TPM2_RC) 0x040) /* add to a parameter-related error */
#define TPM2_RC_SIZE ((TPM2_RC) (TPM2_RC_FMT1 + 0x015)) /* structure is the wrong size */
This typically means that at least one of the command parameters is malformed.
5.Is there any other functionalities to be handle to define the nv_index?
Nope, see the example at the top.
I broke the TPM2_NV_DefineSpace command down to the bytes as an example for you.
We assign the below values for the nv_define
API in U-Boot as given in the example.
We observed the below response (Error 256)
U-Boot> tpm2 nv_define
tpm_tis_spi_probe: gpio-reset is deprecated
Input values size:34 index:0x1400001 attribute:0x44042004
Input to "tpm2_nv_define_space" function values size:34 index:0x1400001 attribute:0x44042004
TPM response [ret:256]: 80 01 00 00 00 0a 00 00 01 00
Error: 256
We also tried nv_define
with initialisation.. Observed same the Error:725
U-Boot> tpm2 init
tpm_tis_spi_probe: gpio-reset is deprecated
U-Boot> tpm2 startup TPM2_SU_CLEAR
TPM response [ret:0]: 80 01 00 00 00 0a 00 00 00 00
U-Boot> tpm2 nv_define
Input values size:34 index:0x1400001 attribute:0x44042004
Input to "tpm2_nv_define_space" function values size:34 index:0x1400001 attribute:0x44042004
TPM response [ret:725]: 80 01 00 00 00 0a 00 00 02 d5
Error: 725
You can verify this by sending these raw bytes to your TPM (or a TPM simulator, here mssim = Microsoft Simulator): echo "80 02 00 00 00 2d 00 00 01 2a 40 00 00 0c 00 00 00 09 40 00 00 09 00 00 00 00 00 00 00 00 0e 01 40 00 01 00 04 44 04 20 04 00 00 00 22" | xxd -r -p | tpm2_send --tcti="device:/dev/tpm0" | xxd -p
we observed the below as response: 80020000001300000000000000000000010000
. What does this signify?
Success, basically.
header:
.tag: 80 02
.size: 00 00 00 13
.responseCode: 00 00 00 00 # success
responseParamSize: 00 00 00 00
authArea:
.nonce: 00 00 # empty (size = 0)
.attributes: 01 # continue session
.sessionAuth: 00 00 # empty (size = 0)
We also tried nv_define with initialisation.. Observed same the Error:725
Please provide me with the raw command bytes you send to the TPM for nv_define
. As mentioned earlier, the TPM reports that a command parameter is invalid.
Please provide me with the raw command bytes you send to the TPM for
nv_define
We printed the command_v2
buffer on lib/tpm-v2.c
and got the below response:
U-Boot> tpm2 init
tpm_tis_spi_probe: gpio-reset is deprecated
U-Boot> tpm2 startup TPM2_SU_CLEAR
Rseponse bfr 988989664TPM response [ret:0]: 80 01 00 00 00 0a 00 00 00 00
U-Boot> tpm2 nv_define
Input values size:34 index:0x1400001 attribute:0x44042004
Input to "tpm2_nv_define_space" values size:34 index:0x1400001 attribute:0x44042004
80 02 00 00 00 2d 00 00 01 2a 40 00 00 0c 00 00 00 09 40 00 00 09 00 00 00 00 00 00 0c 01 40 00 01 00 0b 44 04 20 04 00 00 00 00
We've found that space_size
is not used anywhere on the function but it's received as an parameter to the tpm2_nv_define_space
function. Hence we've modified the command_v2
buffer to have the size as follows,
u8 command_v2[COMMAND_BUFFER_SIZE] = {
.
.
.
/* nv_policy */
tpm_u16(space_size),
};
Now we're receiving a different error (730 - 0x2da
- the TPM was unable to unmarshal a value because there were not enough octets in the input buffer) the RAW command values is as follows,
80 02 00 00 00 2d 00 00 01 2a 40 00 00 0c 00 00 00 09 40 00 00 09 00 00 00 00 00 00 0c 01 40 00 01 00 0b 44 04 20 04 00 00 00 22
So to summarise our questions,
space_size
? Will it define the size of the NV space nvPublic.dataSize
?CC @tkmozhi, @danie007
See below for the two issues with your command stream:
header:
.tag: 80 02
.size: 00 00 00 2d
.commandCode: 00 00 01 2a
handle: 40 00 00 0c # platform
authArea:
.size: 00 00 00 09
.sessionHandle: 40 00 00 09 # password session
.nonce: 00 00 # empty (size = 0)
.attributes: 00
.sessionAuth: 00 00 # empty (size = 0)
auth: # MISSING!, try 00 00 for an empty authValue/password
publicInfo:
.size: 00 0c # WRONG, you need 00 0e (to account for space_size?), just count the bytes below
.nvPublic:
.nvIndex: 01 40 00 01 # arbitrary free NV index
.nameAlg: 00 0b # SHA256
.attributes: 44 04 20 04
.authPolicy: 00 00 # empty policy (size = 0)
.dataSize: 00 22 # size of the NV space: 34 bytes (space_size)
- What is the use of space_size? Will it define the size of the NV space nvPublic.dataSize?
Yes. Seems to be a bug in U-Boot. The space_size
(=nvPublic.dataSize
) is the size of the NV index you want to allocate. For example, if you want to store the bytes 00 11 22 33 in the NV index, you need a space_size
of 4.
- We've also noted that there's size difference (bytes missing) in the RAW command buffer that you've sent vs the one we captured on U-Boot. Is it acceptable or are we missing something?
You are missing something, see above.
If you could solve the problem, please
Thank you!
We tried by modified the command_v2
buffer as below in the do_tpm2_nv_define()
function on lib/tpm-v2.c
u8 command_v2[COMMAND_BUFFER_SIZE] = {
/* header 10 bytes */
tpm_u16(TPM2_ST_SESSIONS), /* TAG */
tpm_u32(offset + nv_policy_size),/* Length */
tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
/* handles 8 bytes */
tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
/* session header 13 bytes */
tpm_u32(9), /* Header size */
tpm_u32(TPM2_RS_PW), /* Password authorisation */
tpm_u16(0), /* nonce_size */
0, /* session_attrs */
tpm_u16(0), /* auth_size */
tpm_u16(0), /* newly added - authValue/password */
/* message 14 bytes + policy */
tpm_u16(14 + nv_policy_size), /* size */ /* Modified - message bytes to 14*/
tpm_u32(space_index),
tpm_u16(TPM2_ALG_SHA256),
tpm_u32(nv_attributes),
tpm_u16(nv_policy_size),
/* nv_policy */
tpm_u16(space_size) /* newly added - size of the NV space*/
};
Observed the TPM response as success.
TPM response [ret:0]: 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00
Also we tried the nv_write command in U-boot with the below options. We received with the Error(644:value is out of range or is not correct for the context)
We prepared the do_tpm2_nv_write_value()
function with reference to the \cmd\tpm-v1.c
file.
U-Boot> tpm2 nv_write 0x1000000 11223344
TPM request [size:39]: 80 02 00 00 00 27 00 00 01 37 40 00 00 0c 02 00 00 00 00 00 00 09 40 00 00 09 00 00 00 00 00 00 04 11 22 33 44 00 00
TPM response [ret:644]: 80 01 00 00 00 0a 00 00 02 84
For nv_read we prepared the do_tpm2_nv_read_Value()
function with reference to the \cmd\tpm-v1.c
file. For that it gets three arguments (index data count) from the user.
index - Nv_index
data - ?
count - counts of data written on the nv_index.
data
specifies in do_tpm2_nv_read_Value()
?@joholl
Kindly provide your feedback on the previous query will be helpful us for using the NV read/write functionalities in u-boot. It would be much appreciated for your help on this query.
Sorry for the late answer.
Observed the TPM response as success.
Nice!
First of all, I just remembered this neat tool: https://apps.microsoft.com/store/detail/tpm-20-parser/9NBLGGH4VQW3?ocid=Apps_O_WOL_en-us_apps-main_education_text-link_brainpop-featured-movie
That will decode your command/response bytes as long as they are well-formed. If you plug in our command bytes, it says:
Header:
Tpm2Lib.CommandHeader
Tag Sessions TpmSt
CommandSize 39 (0x27) uint
CommandCode NvWrite TpmCc
Command Parameters:
Tpm2Lib.Tpm2NvWriteRequest
authHandle - TpmHandle
handle 1073741836 (0x4000000c) uint
nvIndex - TpmHandle
handle 33554432 (0x2000000) uint <-- you need to put the NV index you defined here: 0x01400001
data 0x11223344 byte[4]
offset 0 (0x0) ushort
Sessions [1]
0: 0xTpm2Lib.SessionIn
handle - TpmHandle
handle 1073741833 (0x40000009) uint
nonceCaller 0x byte[0]
attributes None SessionAttr
auth 0x byte[0]
I think you need to change
80 02 00 00 00 27 00 00 01 37 40 00 00 0c 02 00 00 00 00 00 00 09 40 00 00 09 00 00 00 00 00 00 04 11 22 33 44 00 00
to
80 02 00 00 00 27 00 00 01 37 40 00 00 0c 01 40 00 01 00 00 00 09 40 00 00 09 00 00 00 00 00 00 04 11 22 33 44 00 00
Other than that, it looks fine to me, but I have not verified it myself. Hope it helps :)
@saravanj24 I hacked together joholl/tpmstream for answering that kind of question. Thought you might be interested.
python -m tpmstream example NV_Write
Thank you
We verified this tool by sending the Raw byte values of the TPM commands and observed the expected results.
python -m tpmstream example NV_Write
When we tried run the example command in terminal window and no information are display in the screen. Is there any this we missing for executing the example command?
Hi,
We tried tpm2.0 with u-boot in the raspberry pi4, We are observe the error when run the nv_define command in u-boot. can you tell how to add and verify the nv command in u-boot.
CC @tkmozhi