TrustZone API Specification
PRD29-USGC-000089 3.1 ARM Confidential Page 17 of 82
Structured messages are strongly-typed; whenever an attempt is made to decode a parameter in a message,
only the decode function corresponding to the actual type of the parameter can succeed. Strongly-typed
structured messages are an effective and centralized protection to type mismatch or buffer overflow attacks,
where a client attempts to send an ill-formed message to a service.
Messages created using the TZAPI are encoded and decoded in first-in-first-out order. That is, messages must
be decoded in the same order as that in which they were encoded.
4.3.1 Encoding data
The TZAPI automatically creates an encoder when it is valid for a client to send a message to a service, i.e.
whenever the client calls one of the TZOperationPrepare* functions. An encoder is created for the operation
when these prepare operations return success; this is represented by a state change in the operation object. The
client can then make use of the API encoder functions to construct the message sent to the service.
A specific function is defined for each data type to be encoded. The names of the encoder functions start with
the prefix TZEncode*. Array encoding allows a zero-copy implementation by allowing a client to encode a space
of known size in the encoder memory, a pointer to which is then returned to the client. The client can then
generate the data to place into the encoded space in the array before issuing the command to the service.
4.3.2 Decoding data
When an operation has completed, the decoder functions allow the client to decode the service’s response,
subject to the following constraints:
• Where the implementation returns
TZ_SUCCESS or TZ_ERROR_SERVICE, the TZAPI implementation
must return a valid decoder even if the service’s response did not include any message – a decoder
containing no data must be returned if this is the case.
• Where the implementation returns an error code which is neither
TZ_SUCCESS, nor
TZ_ERROR_SERVICE, the decoder is not generated and the decoder functions must not be called by the
client.
A specific function is defined in the TZAPI for each data type which can be decoded. As mentioned previously, in
order for a message to be decoded successfully, the sequence of data types extracted from a message must
match the order in which the message was originally encoded.
The names of the decoder functions start with the prefix TZDecode*. The function TZDecodeArraySpace returns
a pointer to a memory buffer owned by the decoder. The client code must finish using the data in the array slot,
or copy it to a safe location in client owned memory, before releasing the operation for which the decoder was
created.
4.3.3 Empty and NULL arrays
Memory arrays can have zero elements (empty) and can also be NULL. The TZAPI encoders and decoders treat
each of these and an independent case and these can be identified uniquely on decode.
4.3.4 Handling encoder and decoder errors
The TZAPI optimizes error management for encoders and decoders by storing an error state in the encoder or
decoder instance.
The encode functions return no error code. If an error occurs, for example an invalid parameter or an out-of-
memory error, the TZAPI implementation sets the encoder error state. When the client then tries to perform the
operation the API will return the error immediately without issuing the command to the secure environment.
There is no mechanism to reset an encoder once an error has occurred – the operation must be released and a
new one created.
The decode functions also return no error code, and similarly set the decoder error state if an error condition
occurs. When the client wants to check that no decoding error has yet occurred, it can call the function
TZDecodeGetError to retrieve the decoder error state. This helps to optimize the client code size because the
client typically needs to check the decoder error state only when the whole message has been decoded.
The following code sequence decodes a sequence of parameters, and checks the error state at the end of the
decode sequence: