Desktop version

Home arrow Computer Science arrow A Practical Guide to TPM 2.0

Data Details

If you're writing low-level TPM code, this section is crucial to understand because the majority of your bugs will be in this area. When debugging low-level TPM 2.0 code, you need to understand this section in order to properly decode the byte streams being sent to and received from the TPM. The important data concepts to understand are common data structure constructs, canonicalization of the byte stream, and endianness.

Common Structure Constructs

This section describes some commonly used data structures. A good understanding of these is vital because you will see them often.

TPM2B_XXX Structures

All structures that start with a TPM2B_ prefix are sized-byte buffers. Each sized-byte buffer consists of a size and an array of size bytes. Table 5-5 shows a typical structure of this type.

Table 5-5. Definition of the TPM2B_DATA Structure (Table 71 in Part 2 of the TPM 2.0 Specification)

Structure with Union

A union is often contained within a structure and preceded by a union selector. Table 5-6 is an example.

Table 5-6. Definition of the TPMT_HA Structure (Table 69 in Part 2 of the TPM 2.0 Specification)

This structure has two elements: hashAlg, which is used as the selector for the digest union. This is indicated by the brackets surrounding hashAlg in front of the digest parameter. In Table 5-6, hashAlg is the selector for the digest union.

The definition of TPM_HA is shown in Table 5-7.

Table 5-7. Definition of the TPMU_HA Union (Table 68 in Part 2 of the TPM 2.0 Specification)

In general, in a structure, when there is a parameter A that is enclosed in brackets and is in front of parameter B's name, parameter A is a selector for the type of parameter B. In Table 5-7, if hashAlg is set to TPM_ALG_SHA1, then the union element is sha1 [SHA1_DIGEST_SIZE].

The C code generated by Table 5-6 and Table 5-7 is as follows:


The data that is sent to the TPM and received from the TPM is minimized to eliminate any unnecessary bytes in the data stream. This guarantees maximum byte-stream transfer rates to the TPM, because TPMs are often connected to rather slow interface buses such as LPC and SPI. This minimized form of data is called canonical data and is not equivalent to the C-like data structures described in Part 2 of the specification. This concept is crucial to understand if you're dissecting the data stream.

As an example, look at the MAX_NV_BUFFER_2B structure:

typedef struct { UINT16 size;



This structure has a size field and a buffer that is MAX_NV_BUFFER_SIZE bytes long. In the reference implementation, MAX_NV_BUFFER_SIZE is 1,024 bytes. But when this data is sent to the TPM, only the size and the number of bytes specified by the size field are actually sent down the wire. If size equals 10 bytes, only 12 bytes are sent for this structure: 2 for the size field and 10 for the buffer.

In C, unions are used to overlap different types of data structure in a common union. The union's size is the size of the largest type included in the union. A TPM 2.0 data structure that includes a union typically includes a selector that tells what type of data is in the union. A canonical representation of the data only contains the selector and the canonical representation of the structure selected from the union. For example, in the TPMT_HA structure, if the selector, hashAlg, is set to TPM_ALG_SHA1, the digest is SHA1_DIGEST_SIZE bytes, which is much shorter than the maximum size of the union.


TPM data is always in big-endian format when transmitted to or received from the TPM. This means little-endian CPUs, such as the x86 architecture, must always swap bytes before sending data to the TPM and after receiving data from the TPM.

< Prev   CONTENTS   Next >

Related topics