123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /* SPDX-License-Identifier: BSD-3-Clause */
- #include <stdbool.h>
- #include <stdlib.h>
- #include <string.h>
- #include "log.h"
- #include "tpm2.h"
- #include "tpm2_capability.h"
- #define APPEND_CAPABILITY_INFORMATION(capability, field, subfield, max_count) \
- if (fetched_data->data.capability.count > max_count - property_count) { \
- fetched_data->data.capability.count = max_count - property_count; \
- } \
- \
- memmove(&(*capability_data)->data.capability.field[property_count], \
- fetched_data->data.capability.field, \
- fetched_data->data.capability.count * sizeof(fetched_data->data.capability.field[0])); \
- property_count += fetched_data->data.capability.count; \
- \
- (*capability_data)->data.capability.count = property_count; \
- \
- if (more_data && property_count < count && fetched_data->data.capability.count) { \
- property = (*capability_data)->data.capability.field[property_count - 1]subfield + 1; \
- } else { \
- more_data = false; \
- }
- tool_rc tpm2_capability_get(ESYS_CONTEXT *ectx, TPM2_CAP capability,
- UINT32 property, UINT32 count, TPMS_CAPABILITY_DATA **capability_data) {
- TPMI_YES_NO more_data;
- UINT32 property_count = 0;
- *capability_data = NULL;
- do {
- /* fetch capability info */
- TPMS_CAPABILITY_DATA *fetched_data = NULL;
- tool_rc rc = tpm2_get_capability(ectx, ESYS_TR_NONE, ESYS_TR_NONE,
- ESYS_TR_NONE, capability, property, count - property_count,
- &more_data, &fetched_data);
- LOG_INFO("GetCapability: capability: 0x%x, property: 0x%x", capability,
- property);
- if (rc != tool_rc_success) {
- if (*capability_data) {
- free(*capability_data);
- *capability_data = NULL;
- }
- return rc;
- }
- if (fetched_data->capability != capability) {
- LOG_ERR("TPM returned different capability than requested: 0x%x != "
- "0x%x", fetched_data->capability, capability);
- free(fetched_data);
- if (*capability_data) {
- free(*capability_data);
- *capability_data = NULL;
- }
- return tool_rc_general_error;
- }
- if (*capability_data == NULL) {
- /* reuse the TPM's result structure */
- *capability_data = fetched_data;
- if (!more_data) {
- /* there won't be another iteration of the loop, just return the result unmodified */
- return tool_rc_success;
- }
- }
- /* append the TPM's results to the initial structure, as long as there is still space left */
- switch (capability) {
- case TPM2_CAP_ALGS:
- APPEND_CAPABILITY_INFORMATION(algorithms, algProperties, .alg,
- TPM2_MAX_CAP_ALGS);
- break;
- case TPM2_CAP_HANDLES:
- APPEND_CAPABILITY_INFORMATION(handles, handle,,
- TPM2_MAX_CAP_HANDLES);
- break;
- case TPM2_CAP_COMMANDS:
- APPEND_CAPABILITY_INFORMATION(command, commandAttributes,,
- TPM2_MAX_CAP_CC);
- /* workaround because tpm2-tss does not implement attribute commandIndex for TPMA_CC */
- property &= TPMA_CC_COMMANDINDEX_MASK;
- break;
- case TPM2_CAP_PP_COMMANDS:
- APPEND_CAPABILITY_INFORMATION(ppCommands, commandCodes,,
- TPM2_MAX_CAP_CC);
- break;
- case TPM2_CAP_AUDIT_COMMANDS:
- APPEND_CAPABILITY_INFORMATION(auditCommands, commandCodes,,
- TPM2_MAX_CAP_CC);
- break;
- case TPM2_CAP_PCRS:
- APPEND_CAPABILITY_INFORMATION(assignedPCR, pcrSelections, .hash,
- TPM2_NUM_PCR_BANKS);
- break;
- case TPM2_CAP_TPM_PROPERTIES:
- APPEND_CAPABILITY_INFORMATION(tpmProperties, tpmProperty, .property,
- TPM2_MAX_TPM_PROPERTIES);
- break;
- case TPM2_CAP_PCR_PROPERTIES:
- APPEND_CAPABILITY_INFORMATION(pcrProperties, pcrProperty, .tag,
- TPM2_MAX_PCR_PROPERTIES);
- break;
- case TPM2_CAP_ECC_CURVES:
- APPEND_CAPABILITY_INFORMATION(eccCurves, eccCurves,,
- TPM2_MAX_ECC_CURVES);
- break;
- case TPM2_CAP_VENDOR_PROPERTY:
- APPEND_CAPABILITY_INFORMATION(intelPttProperty, property,,
- TPM2_MAX_PTT_PROPERTIES);
- break;
- default:
- LOG_ERR("Unsupported capability: 0x%x\n", capability);
- if (fetched_data != *capability_data) {
- free(fetched_data);
- }
- free(*capability_data);
- *capability_data = NULL;
- return tool_rc_general_error;
- }
- if (fetched_data != *capability_data) {
- free(fetched_data);
- }
- } while (more_data);
- return tool_rc_success;
- }
- tool_rc tpm2_capability_find_vacant_persistent_handle(ESYS_CONTEXT *ctx,
- bool is_platform, TPMI_DH_PERSISTENT *vacant) {
- TPMS_CAPABILITY_DATA *capability_data;
- bool handle_found = false;
- tool_rc rc = tpm2_capability_get(ctx, TPM2_CAP_HANDLES,
- TPM2_PERSISTENT_FIRST, TPM2_MAX_CAP_HANDLES, &capability_data);
- if (rc != tool_rc_success) {
- return rc;
- }
- UINT32 count = capability_data->data.handles.count;
- if (count == 0) {
- /* There aren't any persistent handles, so use the first */
- *vacant = is_platform ? TPM2_PLATFORM_PERSISTENT : TPM2_PERSISTENT_FIRST;
- handle_found = true;
- } else if (count == TPM2_MAX_CAP_HANDLES) {
- /* All persistent handles are already in use */
- goto out;
- } else if (count < TPM2_MAX_CAP_HANDLES) {
- /*
- * iterate over used handles to ensure we're selecting
- * the next available handle.
- *
- * Platform handles start at a higher hange
- */
- UINT32 i;
- for (i = is_platform ? TPM2_PLATFORM_PERSISTENT : TPM2_PERSISTENT_FIRST;
- i <= (UINT32) TPM2_PERSISTENT_LAST; ++i) {
- bool inuse = false;
- UINT32 c;
- for (c = 0; c < count; ++c) {
- if (capability_data->data.handles.handle[c] == i) {
- inuse = true;
- break;
- }
- }
- if (!is_platform && i >= TPM2_PLATFORM_PERSISTENT) {
- break;
- }
- if (!inuse) {
- *vacant = i;
- handle_found = true;
- break;
- }
- }
- }
- out:
- free(capability_data);
- return handle_found ? tool_rc_success : tool_rc_general_error;
- }
|