TPM2_PCR_Allocate may return TPM_RC_SUCCESS without performing the new
allocation, e.g. if the TPM lacks the memory for it. This is only
reported in the allocationSuccess field of the response, see the
TPM 2.0 Library Specification, Part 3: Commands, TPM2_PCR_Allocate.
U-Boot ignores this field, so a refused allocation goes unnoticed and
the board reboots into the unchanged allocation over and over again.
Check allocationSuccess and return an error if the TPM refused the
allocation.
Fixes: 9d2bc92ba7bb ("tpm: add TPM2_PCR_Allocate command")
Signed-off-by: Tycho Kirchner <[email protected]>
---
lib/tpm-v2.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 4c7dfc55650..137bbbd9593 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -596,6 +596,7 @@ u32 tpm2_send_pcr_allocate(struct udevice *dev, const char
*pw,
};
u8 response[COMMAND_BUFFER_SIZE];
size_t response_len = COMMAND_BUFFER_SIZE;
+ u8 success;
u32 i;
int ret;
@@ -642,10 +643,25 @@ u32 tpm2_send_pcr_allocate(struct udevice *dev, const
char *pw,
}
ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
- if (!ret)
- tpm_init(dev);
+ if (ret)
+ return ret;
+
+ /*
+ * The TPM may refuse the new allocation without returning an error
+ * code, e.g. if it lacks the memory for it. Check allocationSuccess,
+ * located after the response header and the parameterSize field.
+ */
+ if (unpack_byte_string(response, response_len, "b",
+ TPM2_HDR_LEN + sizeof(u32), &success))
+ return TPM_LIB_ERROR;
+ if (success != TPMI_YES) {
+ log_err("TPM refused the PCR allocation\n");
+ return TPM_LIB_ERROR;
+ }
- return ret;
+ tpm_init(dev);
+
+ return 0;
}
static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
--
2.47.3