summaryrefslogtreecommitdiff
path: root/firmware/lib/tpm_lite/tlcl.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib/tpm_lite/tlcl.c')
-rw-r--r--firmware/lib/tpm_lite/tlcl.c113
1 files changed, 101 insertions, 12 deletions
diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c
index 37d0fe20..d7dfade9 100644
--- a/firmware/lib/tpm_lite/tlcl.c
+++ b/firmware/lib/tpm_lite/tlcl.c
@@ -834,21 +834,110 @@ uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest,
uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions)
{
- struct s_tpm_getpermissions_cmd cmd;
- uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
- uint8_t* nvdata;
- uint32_t result;
- uint32_t size;
+ uint32_t dummy_attributes;
+ TPM_NV_AUTH_POLICY dummy_policy;
+ uint32_t dummy_policy_size = sizeof(dummy_policy);
- memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd));
- ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index);
- result = TlclSendReceive(cmd.buffer, response, sizeof(response));
- if (result != TPM_SUCCESS)
+ return TlclGetSpaceInfo(index, permissions, &dummy_attributes,
+ &dummy_policy, &dummy_policy_size);
+}
+
+static int DecodePCRInfo(const uint8_t** cursor,
+ const uint8_t* end,
+ TPM_PCR_INFO_SHORT* pcr_info)
+{
+ const size_t available_size = end - *cursor;
+ if (available_size < sizeof(uint16_t)) {
+ return 0;
+ }
+
+ uint16_t size_of_select = 0;
+ FromTpmUint16(*cursor, &size_of_select);
+
+ /* Compute the actual size of the encoded PCR selection (which is a
+ * variable-length field). */
+ const size_t encoded_pcr_info_size = sizeof(TPM_PCR_INFO_SHORT) -
+ sizeof(pcr_info->pcrSelection.pcrSelect) + size_of_select;
+ if (available_size < encoded_pcr_info_size ||
+ size_of_select > sizeof(pcr_info->pcrSelection.pcrSelect)) {
+ return 0;
+ }
+
+ memset(&pcr_info->pcrSelection, 0, sizeof(pcr_info->pcrSelection));
+ const size_t pcr_selection_size =
+ sizeof(size_of_select) + size_of_select;
+ memcpy(&pcr_info->pcrSelection, *cursor, pcr_selection_size);
+ *cursor += pcr_selection_size;
+
+ pcr_info->localityAtRelease = **cursor;
+ (*cursor)++;
+
+ memcpy(&pcr_info->digestAtRelease, *cursor, sizeof(TPM_COMPOSITE_HASH));
+ *cursor += sizeof(TPM_COMPOSITE_HASH);
+
+ return 1;
+}
+
+uint32_t TlclGetSpaceInfo(uint32_t index, uint32_t *attributes, uint32_t *size,
+ void* auth_policy, uint32_t* auth_policy_size)
+{
+ TPM_NV_AUTH_POLICY* policy;
+ uint32_t buffer_size = *auth_policy_size;
+ *auth_policy_size = sizeof(TPM_NV_AUTH_POLICY);
+ if (buffer_size < sizeof(TPM_NV_AUTH_POLICY)) {
+ return TPM_E_BUFFER_SIZE;
+ }
+ policy = auth_policy;
+
+ struct s_tpm_getspaceinfo_cmd cmd;
+ memcpy(&cmd, &tpm_getspaceinfo_cmd, sizeof(cmd));
+ ToTpmUint32(cmd.buffer + tpm_getspaceinfo_cmd.index, index);
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint32_t result = TlclSendReceive(cmd.buffer, response,
+ sizeof(response));
+ if (result != TPM_SUCCESS) {
return result;
+ }
- nvdata = response + kTpmResponseHeaderLength + sizeof(size);
- FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions);
- return result;
+ uint32_t response_size = TpmCommandSize(response);
+ if (response_size > sizeof(response)) {
+ return TPM_E_RESPONSE_TOO_LARGE;
+ }
+
+ const uint8_t* cursor = response + kTpmResponseHeaderLength;
+ uint32_t cap_size = ReadTpmUint32(&cursor);
+ if (cap_size >
+ response_size - sizeof(cap_size) - kTpmResponseHeaderLength) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+ const uint8_t* end = cursor + cap_size;
+
+ cursor += sizeof(uint16_t); /* skip tag */
+ uint32_t response_index = ReadTpmUint32(&cursor);
+ if (index != response_index) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ if (!DecodePCRInfo(&cursor, end, &policy->pcr_info_read) ||
+ !DecodePCRInfo(&cursor, end, &policy->pcr_info_write)) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ /* Make sure that the remaining data in the buffer matches the size of
+ * the remaining fields to decode. */
+ if (end - cursor !=
+ 2 * sizeof(uint32_t) + 3 * sizeof(uint8_t) + sizeof(uint16_t)) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ cursor += sizeof(uint16_t); /* skip TPM_NV_ATTRIBUTES tag */
+ *attributes = ReadTpmUint32(&cursor);
+ cursor += sizeof(uint8_t); /* skip bReadSTClear */
+ cursor += sizeof(uint8_t); /* skip bWriteSTClear */
+ cursor += sizeof(uint8_t); /* skip bWriteDefine */
+ *size = ReadTpmUint32(&cursor);
+
+ return TPM_SUCCESS;
}
uint32_t TlclGetOwnership(uint8_t* owned)