'SPI Hardware Protocol of Trusted Platform Modules (looking for minimal working example)
I am making my first steps in communication with an Infineon OPTIGA TPM SLM 9670 TPM 2.0 via its SPI interface.
I got some first help here, but struggling again.
For starters, I would like to read out the TPM's status register, whose address is given as 0018h.
Interpreting the table from the TPM's SPI Hardware Protocol specification (see below), I do an SPI write of the following four bytes:
0x83 // msb to 1 because I want to read, lower bits to 3 because my xfer consists of 4 bytes
0x00 0x00 0x18 // three register address bytes, naming the register address
When I do an SPI read of 4 bytes (size of the status register) afterwards, I always get FFFFFFFF.
Is this expected or am I doing something wrong?
Solution 1:[1]
SPI Hardware Protocol specification:
The TPM SHALL decode transactions sent to offset 0xD4_xxxx when its CS# is asserted
Basically, you must not forget to offset your address by 0xD4:
0x83 // msb to 1 because I want to read, lower bits to 3 because my xfer consists of 4 bytes
0xD4 0x00 0x18 // three register address bytes, naming the register address
Example Sequence
Tpm2_GetRandom
Note: this assumes that the Linux Kernel initialized the TPM, including having sent the Tpm2_Startup command. If you use mainline linux, you do not need to worry about that.
Legend:
04 -> 81
: Read register 0x04, read value is 0x8104 <- 02
: Write value 0x02 to register 0x04
For a GetRandom, I have the following sequence. Take that with a grain of salt, that is just my guess when reading the kernel driver. The question marks could be checking that the valid bit in the STS register is set (which is probably also checked whenever STS is read).
Operation | My guess of why that is |
---|---|
04 -> 81 |
Access: check activeLocality, valid, requestUse set, probably if locality is used already |
04 <- 02 |
Access: set requestUse |
04 -> A1 |
Access: check requestUse is set |
18 -> 44 |
? |
18 -> 44 |
Status: check commandReady is set |
18 -> 44D00700 |
Status: read burst count |
24 <- 80010000000C0000017B00 |
Command Blob except last byte |
18 -> 8C |
Status: check expect is set |
24 <- 10 |
Command Blob last byte |
18 -> 84 |
Status: check expect bit is clear |
18 <- 20 |
Status: set go bit |
18 -> 94 |
? |
18 -> 94 |
Status: wait for dataAvail |
18 -> 941C0000 |
Status: read burst count |
24 -> 80010000001C00000000 |
Response Blob Header |
18 -> 94 |
Status: wait for dataAvail |
18 -> 94120000 |
Status: read burst count |
24 -> 0010755F8A5B158E44F5CD2EDF784156EED7 |
Response Blob Handles (here none) and Parameters |
18 -> 84 |
Status: wait until valid bit set |
18 -> 84 |
Status: check dataAvail is clear |
18 <- 40 |
Status: set commandReady to reset state machine |
04 <- 20 |
Access: relinquish control |
If you're interested, see roughly this part of the driver.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |