123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /* SPDX-License-Identifier: BSD-3-Clause */
- #ifndef LIB_TPM2_NV_UTIL_H_
- #define LIB_TPM2_NV_UTIL_H_
- #include <tss2/tss2_esys.h>
- #include <string.h>
- #include "log.h"
- #include "tpm2.h"
- #include "tpm2_capability.h"
- #include "tpm2_session.h"
- #include "tpm2_auth_util.h"
- #include "tpm2_hierarchy.h"
- #include "tpm2_util.h"
- /*
- * The default buffer size when one cannot be determined via get capability.
- */
- #define NV_DEFAULT_BUFFER_SIZE 512
- /**
- * Reads the public portion of a Non-Volatile (nv) index.
- * @param context
- * The ESAPI context.
- * @param nv_index
- * The index to read.
- * @param nv_public
- * The public data structure to store the results in.
- * @return
- * tool_rc indicating status.
- */
- static inline tool_rc tpm2_util_nv_read_public(ESYS_CONTEXT *context,
- TPMI_RH_NV_INDEX nv_index, TPM2B_NV_PUBLIC **nv_public) {
- ESYS_TR tr_object;
- tool_rc rc = tpm2_from_tpm_public(context, nv_index, ESYS_TR_NONE,
- ESYS_TR_NONE, ESYS_TR_NONE, &tr_object);
- if (rc != tool_rc_success) {
- return rc;
- }
- rc = tpm2_nv_readpublic(context, tr_object, nv_public, NULL);
- tool_rc tmp_rc = tpm2_close(context, &tr_object);
- if (tmp_rc != tool_rc_success) {
- rc = tmp_rc;
- }
- return rc;
- }
- /**
- * Retrieves the maximum transmission size for an NV buffer by
- * querying the capabilities for TPM2_PT_NV_BUFFER_MAX.
- * @param context
- * The Enhanced System API (ESAPI) context
- * @param size
- * The size of the buffer.
- * @return
- * tool_rc Indicating status.
- */
- static inline tool_rc tpm2_util_nv_max_buffer_size(ESYS_CONTEXT *ectx,
- UINT32 *size) {
- /* Get the maximum read block size */
- TPMS_CAPABILITY_DATA *cap_data;
- TPMI_YES_NO more_data;
- tool_rc rc = tpm2_getcap(ectx, TPM2_CAP_TPM_PROPERTIES,
- TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data);
- if (rc != tool_rc_success) {
- return rc;
- }
- if ( cap_data->data.tpmProperties.tpmProperty[0].property == TPM2_PT_NV_BUFFER_MAX ) {
- *size = cap_data->data.tpmProperties.tpmProperty[0].value;
- } else {
- /* TPM2_PT_NV_BUFFER_MAX is not part of the module spec <= 0.98*/
- *size = NV_DEFAULT_BUFFER_SIZE;
- }
- free(cap_data);
- return rc;
- }
- /**
- * Reads data at Non-Volatile (nv) index.
- * @param ectx
- * The ESAPI context.
- * @param nv_index
- * The index to read.
- * @param size
- * The number of bytes to read.
- * @param offset
- * Offset (in bytes) from which to start reading.
- * @param hierarchy
- * TPMI_RH_NV hierarchy value.
- * @param sdata
- * Session authorization
- * @param sess
- * tpm2 session.
- * @param data_buffer
- * (callee-allocated) Buffer containing data at nv_index
- * @param bytes_written
- * The number of bytes written to data_buffer
- * @return
- * tool_rc indicating status.
- */
- static inline tool_rc tpm2_util_nv_read(ESYS_CONTEXT *ectx,
- TPMI_RH_NV_INDEX nv_index, UINT16 size, UINT16 offset,
- tpm2_loaded_object * auth_hierarchy_obj, UINT8 **data_buffer,
- UINT16 *bytes_written, TPM2B_DIGEST *cp_hash) {
- *data_buffer = NULL;
- TPM2B_NV_PUBLIC *nv_public = NULL;
- tool_rc rc = tpm2_util_nv_read_public(ectx, nv_index, &nv_public);
- if (rc != tool_rc_success) {
- goto out;
- }
- UINT16 data_size = nv_public->nvPublic.dataSize;
- free(nv_public);
- /* if size is 0, assume the whole object */
- if (size == 0) {
- size = data_size;
- }
- if (offset > data_size) {
- LOG_ERR("Requested offset to read from is greater than size. offset=%u"
- ", size=%u", offset, data_size);
- rc = tool_rc_general_error;
- goto out;
- }
- if (offset + size > data_size) {
- LOG_ERR("Requested to read more bytes than available from offset,"
- " offset=%u, request-read-size=%u actual-data-size=%u", offset,
- size, data_size);
- rc = tool_rc_general_error;
- goto out;
- }
- if (cp_hash) {
- goto tpm2_util_nv_read_collect_cp_hash;
- }
- UINT32 max_data_size;
- rc = tpm2_util_nv_max_buffer_size(ectx, &max_data_size);
- if (rc != tool_rc_success) {
- goto out;
- }
- if (max_data_size > TPM2_MAX_NV_BUFFER_SIZE) {
- max_data_size = TPM2_MAX_NV_BUFFER_SIZE;
- } else if (max_data_size == 0) {
- max_data_size = NV_DEFAULT_BUFFER_SIZE;
- }
- tpm2_util_nv_read_collect_cp_hash:
- if (cp_hash) {
- TPM2B_MAX_NV_BUFFER *nv_data;
- rc = tpm2_nv_read(ectx, auth_hierarchy_obj, nv_index, size, offset,
- &nv_data, cp_hash);
- if (rc != tool_rc_success) {
- LOG_ERR("Failed cpHash for NVRAM read at index 0x%X", nv_index);
- }
- goto out;
- }
- *data_buffer = malloc(data_size);
- if (!*data_buffer) {
- LOG_ERR("oom");
- rc = tool_rc_general_error;
- goto out;
- }
- UINT16 data_offset = 0;
- while (size > 0) {
- UINT16 bytes_to_read = size > max_data_size ? max_data_size : size;
- TPM2B_MAX_NV_BUFFER *nv_data;
- rc = tpm2_nv_read(ectx, auth_hierarchy_obj, nv_index, bytes_to_read,
- offset, &nv_data, cp_hash);
- if (rc != tool_rc_success) {
- LOG_ERR("Failed to read NVRAM area at index 0x%X", nv_index);
- goto out;
- }
- size -= nv_data->size;
- offset += nv_data->size;
- memcpy(*data_buffer + data_offset, nv_data->buffer, nv_data->size);
- data_offset += nv_data->size;
- free(nv_data);
- }
- if (bytes_written) {
- *bytes_written = data_offset;
- }
- out:
- if (rc != tool_rc_success && *data_buffer != NULL) {
- free(*data_buffer);
- *data_buffer = NULL;
- }
- return rc;
- }
- static inline bool on_arg_nv_index(int argc, char **argv,
- TPMI_RH_NV_INDEX *nv_index) {
- if (argc > 1) {
- LOG_ERR("Specify single value for NV Index");
- return false;
- }
- if (!argc) {
- LOG_ERR("Specify at least a single value for NV Index");
- return false;
- }
- bool result = tpm2_util_handle_from_optarg(argv[0], nv_index,
- TPM2_HANDLE_FLAGS_NV);
- if (!result) {
- LOG_ERR("Could not convert NV index to number, got: \"%s\"", argv[0]);
- return false;
- }
- if (*nv_index == 0) {
- LOG_ERR("NV Index cannot be 0");
- return false;
- }
- return true;
- }
- #endif /* LIB_TPM2_NV_UTIL_H_ */
|