core/attestation/pcr.h (167 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#ifndef PCR_H_
#define PCR_H_
#include <stdbool.h>
#include <stdint.h>
#include "pcr_data.h"
#include "platform_api.h"
#include "platform_config.h"
#include "crypto/hash.h"
#include "status/rot_status.h"
/* Configurable PCR parameters. Defaults can be overridden in platform_config.h. */
#ifndef PCR_MAX_DIGEST_LENGTH
#define PCR_MAX_DIGEST_LENGTH SHA512_HASH_LENGTH
#endif
#if PCR_MAX_DIGEST_LENGTH < SHA256_HASH_LENGTH
#error "Invalid maximum PCR digest length."
#endif
/* PCR flag to include data included in the measurement calculations */
#define PCR_MEASUREMENT_FLAG_EVENT (1U << 0)
#define PCR_MEASUREMENT_FLAG_VERSION (1U << 1)
#define PCR_MEASUREMENT_FLAG_CONSTANT (1U << 7)
/* TCG log definitions */
#define PCR_TCG_SHA256_ALG_ID 0x0B
#define PCR_TCG_SHA384_ALG_ID 0x0C
#define PCR_TCG_SHA512_ALG_ID 0x0D
#define PCR_TCG_SHA3_256_ALG_ID 0x27
#define PCR_TCG_SHA3_384_ALG_ID 0x28
#define PCR_TCG_SHA3_512_ALG_ID 0x29
#define PCR_TCG_EFI_NO_ACTION_EVENT_TYPE 0x03
#define PCR_TCG_SERVER_PLATFORM_CLASS 0x01
#define PCR_TCG_UINT_SIZE_32 0x01
#define PCR_TCG_LOG_SIGNATURE "Spec ID Event03"
/**
* DMTF measurement value type identifiers indicating what type of data is being reported. Defined
* in the SPDM DSP0274 spec section 10.11.1.1.
*/
enum pcr_dmtf_value_type {
PCR_DMTF_VALUE_TYPE_ROM = 0x00, /**< Immutable ROM. */
PCR_DMTF_VALUE_TYPE_FIRMWARE = 0x01, /**< Mutable firmware. */
PCR_DMTF_VALUE_TYPE_HW_CONFIG = 0x02, /**< Hardware configuration, such as straps. */
PCR_DMTF_VALUE_TYPE_FW_CONFIG = 0x03, /**< Firmware configuration, such as configurable firmware policy. */
PCR_DMTF_VALUE_TYPE_MEAS_MANIFEST = 0x04, /**< Measurement manifest. */
/**
* Other values are defined in SPDM specs 1.2 and 1.3, but are not used here to allow for easier
* compatibility with SPDM 1.1.
*/
PCR_DMTF_VALUE_TYPE_UNUSED = 0x05,
PCR_DMTF_VALUE_TYPE_RESERVED = 0x0b, /**< Reserved. */
};
/**
* Configuration details for a set of measurements in a PCR.
*/
struct pcr_config {
uint8_t num_measurements; /**< The number of measurements in the PCR. */
enum hash_type measurement_algo; /**< Hash algorithm used for measurements in the PCR. */
};
/**
* Descriptor for a single measurement contained in a PCR.
*/
struct pcr_measurement {
uint8_t digest[PCR_MAX_DIGEST_LENGTH]; /**< Digest of the data for the measurement. */
uint8_t measurement[PCR_MAX_DIGEST_LENGTH]; /**< Extended value using the measurement digest. */
const struct pcr_measured_data *measured_data; /**< Accessor for the raw data that was measured. */
uint32_t event_type; /**< TCG event type identifier. */
uint8_t version; /**< Version associated with the measurement data. */
uint8_t measurement_config; /**< Indicates additional data to include in measurement digests. */
enum pcr_dmtf_value_type dmtf_type; /**< DMTF value type identifier. */
bool spdm_not_tcb; /**< Flag to skip the measurement from SPDM TCB reports. */
};
/**
* Descriptor for a single PCR managed by the device, which contains a list of individual
* measurements.
*/
struct pcr_bank {
struct pcr_measurement *measurement_list; /**< List of measurements in the PCR. */
struct pcr_config config; /**< Configuration for the PCR and measurements. */
bool explicit_measurement; /**< Flag to indicate that the PCR is an explicit measurement. */
platform_mutex lock; /**< Synchronization lock. */
};
#pragma pack(push, 1)
/**
* Header for the TCG_PCR_EVENT2 log structure.
*/
struct pcr_tcg_event2_header {
uint32_t pcr_index; /**< Index for the PCR containing the measurement. */
uint32_t event_type; /**< Event identifier for the measurement. */
uint32_t digest_count; /**< Number of digests calculated for the event. */
uint16_t digest_algorithm_id; /**< ID of hashing algorithm used to calculate the digest. */
};
/**
* TCG event entry with a single SHA-256 digest.
*/
struct pcr_tcg_event2_sha256 {
struct pcr_tcg_event2_header header; /**< Event entry header. */
uint8_t digest[SHA256_HASH_LENGTH]; /**< SHA-256 digest that was extended to PCR. */
uint32_t event_size; /**< Length of the data that was measured. */
};
/**
* TCG event entry with a single SHA-384 digest.
*/
struct pcr_tcg_event2_sha384 {
struct pcr_tcg_event2_header header; /**< Event entry header. */
uint8_t digest[SHA384_HASH_LENGTH]; /**< SHA-384 digest that was extended to PCR. */
uint32_t event_size; /**< Length of the data that was measured. */
};
/**
* TCG event entry with a single SHA-512 digest.
*/
struct pcr_tcg_event2_sha512 {
struct pcr_tcg_event2_header header; /**< Event entry header. */
uint8_t digest[SHA512_HASH_LENGTH]; /**< SHA-512 digest that was extended to PCR. */
uint32_t event_size; /**< Length of the data that was measured. */
};
/**
* TCG event entry using the TCG_PCR_EVENT log structure.
*/
struct pcr_tcg_event {
uint32_t pcr_index; /**< Index for the PCR containing the measurement. */
uint32_t event_type; /**< Event identifier for the measurement. */
uint8_t digest[SHA1_HASH_LENGTH]; /**< SHA-1 digest for the event. */
uint32_t event_size; /**< Length of the data that was measured. */
//uint8_t event[0]; /**< Event data. Commented out since not used by Cerberus. */
};
/**
* TCG event log algorithm descriptor.
*/
struct pcr_tcg_algorithm {
uint16_t digest_algorithm_id; /**< Identifier for a hashing algorithm used in the log. */
uint16_t digest_size; /**< Length of the digest that is generated by the specified algorithm. */
};
/**
* TCG event log header.
*/
struct pcr_tcg_log_header {
uint8_t signature[16]; /**< The null terminated ASCII string "Spec ID Event03" */
uint32_t platform_class; /**< Platform class as defined in TCG spec */
uint8_t spec_version_minor; /**< Spec minor version number */
uint8_t spec_version_major; /**< Spec major version number */
uint8_t spec_errata; /**< Spec errata supported */
uint8_t uintn_size; /**< Size of uint fields */
uint32_t num_algorithms; /**< Number of hashing algorithms used in log */
struct pcr_tcg_algorithm digest_size[3]; /**< List of hashing algorithm descriptors */
uint8_t vendor_info_size; /**< Size of vendorInfo */
//uint8_t vendor_info[0]; /**< Vendor-specific extra information. Commented out since not used by Cerberus */
};
#pragma pack(pop)
int pcr_init (struct pcr_bank *pcr, const struct pcr_config *config);
void pcr_release (struct pcr_bank *pcr);
int pcr_get_num_measurements (struct pcr_bank *pcr);
int pcr_check_measurement_index (struct pcr_bank *pcr, uint8_t measurement_index);
enum hash_type pcr_get_hash_algorithm (struct pcr_bank *pcr);
int pcr_get_digest_length (struct pcr_bank *pcr);
int pcr_set_tcg_event_type (struct pcr_bank *pcr, uint8_t measurement_index, uint32_t event_type);
int pcr_get_tcg_event_type (struct pcr_bank *pcr, uint8_t measurement_index, uint32_t *event_type);
int pcr_set_dmtf_value_type (struct pcr_bank *pcr, uint8_t measurement_index,
enum pcr_dmtf_value_type value_type, bool is_not_tcb);
int pcr_get_dmtf_value_type (struct pcr_bank *pcr, uint8_t measurement_index,
enum pcr_dmtf_value_type *value_type);
int pcr_is_measurement_in_tcb (struct pcr_bank *pcr, uint8_t measurement_index);
int pcr_update_digest (struct pcr_bank *pcr, uint8_t measurement_index, const uint8_t *digest,
size_t digest_len);
int pcr_update_buffer (struct pcr_bank *pcr, const struct hash_engine *hash,
uint8_t measurement_index, const uint8_t *buf, size_t buf_len, bool include_event);
int pcr_update_versioned_buffer (struct pcr_bank *pcr, const struct hash_engine *hash,
uint8_t measurement_index, const uint8_t *buf, size_t buf_len, bool include_event,
uint8_t version);
int pcr_const_update_digest (struct pcr_bank *pcr, uint8_t measurement_index, const uint8_t *digest,
size_t digest_len);
int pcr_const_update_buffer (struct pcr_bank *pcr, const struct hash_engine *hash,
uint8_t measurement_index, const uint8_t *buf, size_t buf_len, bool include_event);
int pcr_const_update_versioned_buffer (struct pcr_bank *pcr, const struct hash_engine *hash,
uint8_t measurement_index, const uint8_t *buf, size_t buf_len, bool include_event,
uint8_t version);
int pcr_invalidate_measurement (struct pcr_bank *pcr, uint8_t measurement_index);
int pcr_compute (struct pcr_bank *pcr, const struct hash_engine *hash, bool lock,
uint8_t *measurement, size_t length);
int pcr_get_measurement (struct pcr_bank *pcr, uint8_t measurement_index,
struct pcr_measurement *measurement);
int pcr_get_all_measurements (struct pcr_bank *pcr,
const struct pcr_measurement **measurement_list);
int pcr_is_measurement_data_available (struct pcr_bank *pcr, uint8_t measurement_index);
int pcr_set_measurement_data (struct pcr_bank *pcr, uint8_t measurement_index,
const struct pcr_measured_data *measurement_data);
int pcr_get_measurement_data (struct pcr_bank *pcr, uint8_t measurement_index, size_t offset,
uint8_t *buffer, size_t length, size_t *total_len);
int pcr_hash_measurement_data (struct pcr_bank *pcr, uint8_t measurement_index,
const struct hash_engine *hash, enum hash_type hash_type, uint8_t *buffer, size_t length);
int pcr_get_tcg_log (struct pcr_bank *pcr, uint32_t pcr_num, size_t offset, uint8_t *buffer,
size_t length, size_t *total_len);
int pcr_lock (struct pcr_bank *pcr);
int pcr_unlock (struct pcr_bank *pcr);
#define PCR_ERROR(code) ROT_ERROR (ROT_MODULE_PCR, code)
/**
* Error codes that can be generated by the PCR management module.
*/
enum {
PCR_INVALID_ARGUMENT = PCR_ERROR (0x00), /**< Input parameter is null or not valid. */
PCR_NO_MEMORY = PCR_ERROR (0x01), /**< Memory allocation failed. */
PCR_UNSUPPORTED_ALGO = PCR_ERROR (0x02), /**< Unsupported hashing algorithm. */
PCR_INVALID_PCR = PCR_ERROR (0x03), /**< Invalid PCR bank. */
PCR_INVALID_TYPE = PCR_ERROR (0x04), /**< Invalid measurement type. */
PCR_INVALID_INDEX = PCR_ERROR (0x05), /**< Invalid measurement index. */
PCR_INVALID_DATA_TYPE = PCR_ERROR (0x06), /**< Invalid PCR measured data type. */
PCR_MEASURED_DATA_INVALID_MEMORY = PCR_ERROR (0x08), /**< PCR Measured data memory location is null or invalid */
PCR_MEASURED_DATA_INVALID_FLASH_DEVICE = PCR_ERROR (0x09), /**< Flash device storing PCR Measured data is null or invalid */
PCR_MEASURED_DATA_INVALID_CALLBACK = PCR_ERROR (0x0a), /**< Callback to retrieve PCR Measured data is null or invalid */
PCR_INCORRECT_DIGEST_LENGTH = PCR_ERROR (0x0b), /**< The digest length is not correct for the PCR. */
PCR_SMALL_OUTPUT_BUFFER = PCR_ERROR (0x0c), /**< The output buffer is not large enough for the PCR. */
PCR_INVALID_VALUE_TYPE = PCR_ERROR (0x0d), /**< Invalid DMTF value type identifier. */
PCR_INVALID_SEQUENTIAL_ID = PCR_ERROR (0x0e), /**< Invalid sequential measurement ID. */
PCR_MEASURED_DATA_NOT_AVIALABLE = PCR_ERROR (0x0f), /**< The raw measured data is not available for the measurement. */
PCR_MEASURED_DATA_NO_HASH_CALLBACK = PCR_ERROR (0x10), /**< The measured data does not provide a hash callback. */
PCR_CONSTANT_MEASUREMENT = PCR_ERROR (0x11), /**< Attempt to update a constant measurement. */
};
#endif /* PCR_H_ */