[U-Boot] [PATCH v2] tpm: Add TPM command library

Pfau, Reinhard Pfau at gdsys.de
Thu Feb 28 15:50:28 CET 2013


Hi,

While digging through the code, some question arises.
So let me drop some notes about the patch:

( I apologize for some weird word wraps in the quoted text, but I have
to use
a well known UMA which seems to be too stupid to keep lines of text
without additional
word wraps...)

> -----Original Message-----
> From: u-boot-bounces at lists.denx.de 
> [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Che-Liang Chiou
> Sent: Friday, February 15, 2013 12:01 AM
> To: u-boot at lists.denx.de
> Subject: [U-Boot] [PATCH v2] tpm: Add TPM command library
> 
> TPM command library implements a subset of TPM commands defined in TCG
> Main Specification 1.2 that are useful for implementing secure boot.
> More TPM commands could be added out of necessity.
> 
> You may exercise these commands through the 'tpm' command.  
> However, the
> raw TPM commands are too primitive for writing secure boot in command
> interpreter scripts; so the 'tpm' command also provides 
> helper functions
> to make scripting easier.
> 
> For example, to define a counter in TPM non-volatile storage and
> initialize it to zero:
> 
> $ tpm init
> $ tpm startup TPM_ST_CLEAR
> $ tpm nv_define d 0x1001 0x1
> $ tpm nv_write d 0x1001 0
> 
> And then increment the counter by one:
> 
> $ tpm nv_read d 0x1001 i
> $ setexpr.l i $i + 1
> $ tpm nv_write d 0x1001 $i
> 
> Signed-off-by: Che-Liang Chiou <clchiou at chromium.org>
> ---
>  common/cmd_tpm.c         | 709 
> +++++++++++++++++++++++++++++++++++++++--------
>  include/{tpm.h => tis.h} |   8 +-
>  include/tpm.h            | 197 ++++++++++---
>  lib/Makefile             |   1 +
>  lib/tpm.c                | 569 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 1339 insertions(+), 145 deletions(-)
>  copy include/{tpm.h => tis.h} (95%)
>  create mode 100644 lib/tpm.c
>
[snip] 
> diff --git a/lib/tpm.c b/lib/tpm.c
> new file mode 100644
> index 0000000..7d13951
> --- /dev/null
> +++ b/lib/tpm.c
[snip]
> +/**
> + * Send a TPM command and return response's return code.
> + *
> + * @param command	byte string of TPM command
> + * @return return code of the TPM response
> + */
> +static uint32_t tpm_send_command(const void *command)
> +{
> +	uint8_t response[COMMAND_BUFFER_SIZE];
> +	size_t response_length = sizeof(response);
> +	uint32_t err;
> +
> +	err = tis_sendrecv(command, tpm_command_size(command),
> +			response, &response_length);
> +	if (err)
> +		return err;
> +
> +	return tpm_return_code(response);
> +}

Using the result of tis_sendrecv would be OK with the I2C-TPM patch
posted on this ML about a year ago.
The implementation of tis_sendrecv in generic_lpc_tpm.c returns the
value (1) on error instead of -1
(as documented in the header file). Since 1 is a well defined TPM result
code (TPM_AUTHFAIL) this could
result in some problems.
(But I think, this is a bug in the current generic_lpc_tpm driver...)

[snip]

> +
> +uint32_t tpm_nv_read_value(uint32_t index, void *data, 
> uint32_t count)
> +{
> +	const uint8_t command[22] = {
> +		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
> +	};
> +	const size_t index_offset = 10;
> +	const size_t length_offset = 18;
> +	const size_t data_size_offset = 10;
> +	const size_t data_offset = 14;
> +	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
> +	uint32_t response_length = sizeof(response), data_size;
> +	uint32_t err;
> +
> +	if (pack_byte_string(buf, sizeof(buf), "sdd",
> +				0, command, sizeof(command),
> +				index_offset, index,
> +				length_offset, count))
> +		return TPM_LIB_ERROR;
> +	err = tis_sendrecv(buf, tpm_command_size(buf),
> +			response, &response_length);
> +	if (err)
> +		return err;

At this point we should add something like:

	err = tpm_return_code(response);
	if (err)
		return err;

to return the "real" result code from the TPM in case of an error.
Else the following code will map all TPM errors to TPM_LIB_ERROR
(since unpack_byte_string will fail).

Same in the other funcs which interpret the result of the command
(tpm_extend, tpm_pcr_read, rtpm_read_pubek, tpm_get_capability).

> +	if (unpack_byte_string(response, response_length, "d",
> +				data_size_offset, &data_size))
> +		return TPM_LIB_ERROR;
> +	if (data_size > count)
> +		return TPM_LIB_ERROR;
> +	if (unpack_byte_string(response, response_length, "s",
> +				data_offset, data, data_size))
> +		return TPM_LIB_ERROR;
> +
> +	return 0;
> +}
> +
> +uint32_t tpm_nv_write_value(uint32_t index, const void 
> *data, uint32_t length)
> +{
> +	const uint8_t command[256] = {
> +		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
> +	};
> +	const size_t command_size_offset = 2;
> +	const size_t index_offset = 10;
> +	const size_t length_offset = 18;
> +	const size_t data_offset = 22;
> +	const size_t write_info_size = 12;
> +	const uint32_t total_length =
> +		TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
> +	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
> +	uint32_t response_length = sizeof(response);
> +	uint32_t err;
> +
> +	if (pack_byte_string(buf, sizeof(buf), "sddds",
> +				0, command, sizeof(command),
> +				command_size_offset, total_length,
> +				index_offset, index,
> +				length_offset, length,
> +				data_offset, data, length))
> +		return TPM_LIB_ERROR;
> +	err = tis_sendrecv(buf, tpm_command_size(buf),
> +			response, &response_length);
> +	if (err)
> +		return err;
> +
> +	return 0;

Why not just call tpm_send_command(buf) here like in the other funcs
where the
Result does not need further interpretation (beside the return code)?


Beside theese remarks: I like Your patch, since one of our upcoming
boards also uses
a TPM to check system integrity at boot time :-)


Greetings,
Reinhard Pfau.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/ms-tnef
Size: 5088 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130228/fb2e6c5b/attachment.bin>


More information about the U-Boot mailing list