core/manifest/manifest_pcr.c (120 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #include <stddef.h> #include <stdlib.h> #include <string.h> #include "manifest_logging.h" #include "manifest_pcr.h" #include "platform_api.h" #include "common/unused.h" /** * Initialize common manifest PCR management. This is only intended to be initialized as part of * a parent module. No null checking will be done on the input parameters. * * @param pcr The PCR management to initialize. * @param hash The hash engine to use for generating manifest measurements. * @param store The PCR store to update as the manifest changes. * @param manifest_measurement The identifier for the manifest measurement in the PCR. * @param manifest_id_measurement The identifier for the manifest ID measurement in the PCR. * @param manifest_platform_id_measurement The identifier for the manifest platform ID measurement * in the PCR. * @param error The error code to return if measurements are not unique. * * @return 0 if the PCR manager was successfully initialized or an error code. */ int manifest_pcr_init (struct manifest_pcr *pcr, const struct hash_engine *hash, struct pcr_store *store, uint16_t manifest_measurement, uint16_t manifest_id_measurement, uint16_t manifest_platform_id_measurement, int not_unique) { pcr->hash = hash; pcr->store = store; pcr->manifest_measurement = manifest_measurement; pcr->manifest_id_measurement = manifest_id_measurement; pcr->manifest_platform_id_measurement = manifest_platform_id_measurement; return manifest_pcr_check_measurements (pcr, -1, not_unique); } /** * Release the resources used for manifest PCR management. * * @param pcr The PCR manager to release. */ void manifest_pcr_release (const struct manifest_pcr *pcr) { UNUSED (pcr); } /** * Check that the configured measurements for the manifest are valid. This will also check that the * PCR manager was properly initialized. * * @param pcr The PCR manager to check. * @param invalid_arg The error code to return for a null pointer. * @param not_unique The error code to return if measurements are not unique. * * @return 0 if the measurements are all valid or an error code. */ int manifest_pcr_check_measurements (const struct manifest_pcr *pcr, int invalid_arg, int not_unique) { int status; if ((pcr == NULL) || (pcr->hash == NULL) || (pcr->store == NULL)) { return invalid_arg; } if ((pcr->manifest_measurement == pcr->manifest_id_measurement) || (pcr->manifest_measurement == pcr->manifest_platform_id_measurement) || (pcr->manifest_id_measurement == pcr->manifest_platform_id_measurement)) { return not_unique; } status = pcr_store_check_measurement_type (pcr->store, pcr->manifest_measurement); if (status != 0) { return status; } status = pcr_store_check_measurement_type (pcr->store, pcr->manifest_id_measurement); if (status != 0) { return status; } status = pcr_store_check_measurement_type (pcr->store, pcr->manifest_platform_id_measurement); if (status != 0) { return status; } return 0; } /** * Record all measurements for the provided manifest. Errors generating manifest measurements * will be logged and will prevent updates to subsequent measurements. * * @param pcr The PCR manager that will record the measurement. * @param active The manifest to measure. * * @return 0 if the manifest was measured successfully or an error code. */ int manifest_pcr_record_manifest_measurement (const struct manifest_pcr *pcr, const struct manifest *active) { return manifest_pcr_measure_manifest (active, pcr->hash, pcr->store, pcr->manifest_measurement, pcr->manifest_id_measurement, pcr->manifest_platform_id_measurement); } /** * Measure a manifest into the specified measurement IDs. Errors generating manifest measurements * will be logged and will prevent updates to subsequent measurements. * * This has the same behavior as manifest_pcr_record_manifest_measurement but can be called from * contexts that do not have a manifest_pcr instance. * * @param active The manifest to measure. * @param hash The hash engine to use for generating manifest measurements. * @param store The PCR store to update with manifest measurements. * @param manifest_measurement The identifier for the manifest measurement in the PCR. * @param manifest_id_measurement The identifier for the manifest ID measurement in the PCR. * @param manifest_platform_id_measurement The identifier for the manifest platform ID measurement * in the PCR. * * @return 0 if the manifest was measured successfully or an error code. */ int manifest_pcr_measure_manifest (const struct manifest *active, const struct hash_engine *hash, struct pcr_store *store, uint16_t manifest_measurement, uint16_t manifest_id_measurement, uint16_t manifest_platform_id_measurement) { uint8_t manifest_digest[HASH_MAX_HASH_LEN] = {0}; int digest_length = SHA256_HASH_LENGTH; uint8_t id[5]; char *platform_id = NULL; char empty_string = '\0'; int status; if (active) { digest_length = active->get_hash (active, hash, manifest_digest, sizeof (manifest_digest)); if (ROT_IS_ERROR (digest_length)) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_GET_MEASUREMENT_FAIL, manifest_measurement, digest_length); return digest_length; } } status = pcr_store_update_versioned_buffer (store, hash, manifest_measurement, manifest_digest, digest_length, true, 0); if (status != 0) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_RECORD_MEASUREMENT_FAIL, manifest_measurement, status); return status; } if (active == NULL) { memset (id, 0, sizeof (id)); } else { id[0] = 1; status = active->get_id (active, (uint32_t*) &id[1]); if (status != 0) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_GET_ID_FAIL, manifest_id_measurement, status); return status; } } status = pcr_store_update_versioned_buffer (store, hash, manifest_id_measurement, id, sizeof (id), true, 0); if (status != 0) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_RECORD_MEASUREMENT_FAIL, manifest_id_measurement, status); return status; } if (active == NULL) { platform_id = &empty_string; } else { status = active->get_platform_id (active, &platform_id, 0); if (status != 0) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_GET_PLATFORM_ID_FAIL, manifest_platform_id_measurement, status); return status; } } status = pcr_store_update_versioned_buffer (store, hash, manifest_platform_id_measurement, (uint8_t*) platform_id, strlen (platform_id) + 1, true, 0); if (status != 0) { debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST, MANIFEST_LOGGING_RECORD_MEASUREMENT_FAIL, manifest_platform_id_measurement, status); } if (active != NULL) { active->free_platform_id (active, platform_id); } return status; }