Skip to content

tpm2_send: Validate command_size before computing data_size#3549

Merged
JuergenReppSIT merged 1 commit into
tpm2-software:masterfrom
hyperfinitism:fix/command-size-check
Feb 18, 2026
Merged

tpm2_send: Validate command_size before computing data_size#3549
JuergenReppSIT merged 1 commit into
tpm2-software:masterfrom
hyperfinitism:fix/command-size-check

Conversation

@hyperfinitism
Copy link
Copy Markdown
Contributor

Background

In lib/tpm2_header.h, TPM command buffers are represented by the tpm2_command_header union, which exposes both a raw byte view and a structured header view (tag, size, command_code, data[]).

union tpm2_command_header {
struct {
TPMI_ST_COMMAND_TAG tag; // uint16
UINT32 size; //
TPM2_CC command_code;
UINT8 data[];
}__attribute__((packed));
UINT8 bytes[0];
};

TPM2_COMMAND_HEADER_SIZE is defined as sizeof(tpm2_command_header), i.e., the fixed-size header portion (excluding the variable-length data[]). The helper tpm2_command_header_get_size() returns either the full command size (include_header=true) or payload size (include_header=false, computed as size - TPM2_COMMAND_HEADER_SIZE).

static inline UINT32 tpm2_command_header_get_size(const tpm2_command_header *command,
bool include_header) {
UINT32 size = tpm2_util_ntoh_32(command->size);
return include_header ? size : size - TPM2_COMMAND_HEADER_SIZE;
}

In tools/tpm2_send.c, the code currently derives both command_size and data_size from the input header, and then validates size relationships before allocating/parsing the command body.​

const tpm2_command_header *header = tpm2_command_header_from_bytes(buffer);
UINT32 command_size = tpm2_command_header_get_size(header, true);
UINT32 data_size = tpm2_command_header_get_size(header, false);
if (command_size > TPM2_MAX_SIZE || command_size < data_size) {
LOG_ERR("Command buffer %"PRIu32" bytes cannot be smaller then the "
"encapsulated data %"PRIu32" bytes, and can not be bigger than"
" the maximum buffer size", command_size, data_size);
return -1;
}

Problem

If malformed input sets tpm2_command_header.size to a value smaller than TPM2_COMMAND_HEADER_SIZE, computing data_size (size - TPM2_COMMAND_HEADER_SIZE) causes unsigned overflow.

As a result, later checks may report a confusing error path/message based on overflowed values rather than the actual root cause (invalid header-size field).

For example:

# malformed header:
#   tag: 00 in TPMI_ST_COMMAND_TAG (uint16)
#   size: 00 00 00 09 in UINT32
#   command_code: 00 00 00 00 in TPM2_CC (UINT32)
#   data: {} in uint8[]
printf "00000000000900000000" | xxd -r -p > malformed_command.bin
tpm2_send < malformed_command.bin

Current behavior can produce an error like:

ERROR: Command buffer 9 bytes cannot be smaller then the encapsulated data 4294967295 bytes, and can not be bigger than the maximum buffer size
ERROR: failed to read TPM2 command buffer from file
ERROR: Unable to run tpm2_send

This message is misleading when the real issue is that the encoded command size is smaller than the required header size.

Fix

This PR changes validation order in tpm2_send:

  • Read command_size.
  • Validate command_size >= TPM2_COMMAND_HEADER_SIZE.
  • Validate command_size <= TPM2_MAX_SIZE.
  • Only then derive data_size.

With this order, overflow during data_size derivation is avoided for malformed short-size headers. Since data_size is then derived from a validated command_size, the command_size < data_size check becomes unnecessary and is removed.

After those changes, the command

printf "00000000000900000000" | xxd -r -p > malformed_command.bin
tpm2_send < malformed_command.bin

yields a relevant error message:

ERROR: Command buffer size 9 is smaller than command header size 10
ERROR: failed to read TPM2 command buffer from file
ERROR: Unable to run tpm2_send

Signed-off-by: Takuma IMAMURA <209989118+hyperfinitism@users.noreply.github.com>
@JuergenReppSIT JuergenReppSIT merged commit c0f8d04 into tpm2-software:master Feb 18, 2026
23 checks passed
@hyperfinitism hyperfinitism deleted the fix/command-size-check branch February 25, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants