Hi Shahriyar

On Fri, 24 Jul 2026 at 13:34, Shahriyar Jalayeri <[email protected]>
wrote:

> The length of a TPM reply is set by the device: tpm_sendrecv_command()
> stores the number of bytes received, caps it only at the command buffer
> size, and reports success whenever the reply's return code is 0. Callers
> then use that length without checking it:
>
> tpm2_get_capability() copies response_len - 15 bytes into the caller's
> buffer. A reply shorter than 15 bytes underflows the subtraction into a
> huge memcpy; a reply longer than the buffer (sized for prop_count
> properties) overruns it.
>
> tpm1_load_key2_oiap() and tpm1_get_pub_key_oiap() pass response_length
> - 41 to verify_response_auth(), which a reply shorter than 41 bytes
> underflows.
>
> A TPM sits on a discrete SPI/I2C/LPC bus that is physically accessible, so
> a reply this malformed is reachable by a bus interposer or a faulty part;
> on the TPM2 path this parsing runs during measured boot.
>
> Check the reported length against the header before the subtraction, and
> against the caller's buffer before the GetCapability copy.
>
> Fixes: 69cd8f0681f4 ("tpm: add TPM2_GetCapability command support")
> Fixes: be6c1529c1ce ("tpm: add AUTH1 cmds for LoadKey2 and GetPubKey")
> Signed-off-by: Shahriyar Jalayeri <[email protected]>
> Acked-by: Miquel Raynal <[email protected]>
> ---
>  lib/tpm-v1.c | 6 ++++++
>  lib/tpm-v2.c | 8 ++++++++
>  2 files changed, 14 insertions(+)
>
> diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
> index a6727c575fd..5fd22924b28 100644
> --- a/lib/tpm-v1.c
> +++ b/lib/tpm-v1.c
> @@ -757,6 +757,9 @@ u32 tpm1_load_key2_oiap(struct udevice *dev, u32
> parent_handle, const void *key,
>                 return err;
>         }
>
> +       if (response_length < TPM_RESPONSE_AUTH_LENGTH)
> +               return TPM_LIB_ERROR;
> +
>         err = verify_response_auth(0x00000041, response,
>                                    response_length -
> TPM_RESPONSE_AUTH_LENGTH,
>                                    4, &oiap_session,
> @@ -817,6 +820,9 @@ u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32
> key_handle,
>                         oiap_session.valid = 0;
>                 return err;
>         }
> +       if (response_length < TPM_RESPONSE_AUTH_LENGTH)
> +               return TPM_LIB_ERROR;
> +
>         err = verify_response_auth(0x00000021, response,
>                                    response_length -
> TPM_RESPONSE_AUTH_LENGTH,
>                                    0, &oiap_session,
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index f443b738f82..aa4d3866d7b 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -519,6 +519,14 @@ u32 tpm2_get_capability(struct udevice *dev, u32
> capability, u32 property,
>          */
>         properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
>                          sizeof(u8) + sizeof(u32);
> +       if (response_len < properties_off)
> +               return TPM_LIB_ERROR;
> +
> +       if (capability == TPM2_CAP_TPM_PROPERTIES &&
> +           response_len - properties_off >
> +           sizeof(u32) + prop_count * sizeof(struct tpms_tagged_property))
> +               return TPM_LIB_ERROR;
> +
>

Thios doesn't llike a problem for the capabilities only. Can't we
update tpm_sendrecv_command() with an extra argument of the expected
response lenght? We can then check that for even invocation in the function
itself if the *size_ptr != NULL

Thanks
/Ilias

>         memcpy(buf, &response[properties_off], response_len -
> properties_off);
>
>         return 0;
>
> --
> 2.43.0
>
>

Reply via email to