Project-Cerberus/core/manifest/manifest_pcr.c

156 строки
4.8 KiB
C
Исходник Обычный вид История

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
Add flexibility to how firmware updates are handled. Improve platform porting. There are a few changes included here: 1. Enhanced the firmware updater to provide options on how and when the recovery and revocation steps get performed. It is now possible to always make sure the recovery image is updated and only do recovery updates and revocation after a device reset. To easily support implementations that want to use different mechanisms for update, the firmware update handler code was refactored out of the task context into another module, with various configurations and derivations to support the desired behavior. 2. The platform abstraction for tasks put too much logic in the task context that needs to be implemented for each platform. New task abstractions have been added that leave all the handling logic in the common code and only require the different platforms to provide a minimal wrapper for the actual task creation and execution. This was leveraged to manage the different ways firmware update can now be handled. Task ports for FreeRTOS were created. 3. There were a few places where the platform_clock APIs were being misused, making assumptions about the API that didn't hold across platform ports. These usages were cleaned up. Specifically for component attestation, the way it determined the time until the next event was not robust across platforms. A new platform API was added to serve this use case. This API was also required for the new platform task abstractions. 4. To avoid platform assumptions and platform API misuse, a common header file has been created that all core code now references. This platform API header file defines the functions that will exist for any port and specifies the contract and usage of these functions. 5. There was a bug in the way the Linux platform port calculated durations that caused it to add an extra second in certain scenarios.
2022-11-17 00:48:36 +03:00
#include "platform_api.h"
#include "manifest_pcr.h"
#include "manifest_logging.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 PCR measurements.
* @param store The PCR store to update as the CFM 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, struct hash_engine *hash,
struct pcr_store *store, uint16_t manifest_measurement, uint16_t manifest_id_measurement,
uint16_t manifest_platform_id_measurement, int error)
{
int status;
if ((manifest_measurement == manifest_id_measurement) ||
(manifest_measurement == manifest_platform_id_measurement) ||
(manifest_id_measurement == manifest_platform_id_measurement)) {
return error;
}
status = pcr_store_check_measurement_type (store, manifest_measurement);
if (status != 0) {
return status;
}
status = pcr_store_check_measurement_type (store, manifest_id_measurement);
if (status != 0) {
return status;
}
status = pcr_store_check_measurement_type (store, manifest_platform_id_measurement);
if (status != 0) {
return status;
}
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 0;
}
/**
* Release the resources used for manifest PCR management.
*
* @param pcr The PCR manager to release.
*/
void manifest_pcr_release (struct manifest_pcr *pcr)
{
UNUSED (pcr);
}
/**
* Record the measurement for the provided manifest.
*
* @param pcr The PCR manager that will record the measurement.
* @param active The manifest to measure.
*/
void manifest_pcr_record_manifest_measurement (const struct manifest_pcr *pcr,
struct manifest *active)
{
uint8_t manifest_measurement[SHA512_HASH_LENGTH] = {0};
int measurement_length = SHA256_HASH_LENGTH;
uint8_t id[5];
char *platform_id = NULL;
char empty_string = '\0';
int status;
if (active) {
measurement_length = active->get_hash (active, pcr->hash, manifest_measurement,
sizeof (manifest_measurement));
if (ROT_IS_ERROR (measurement_length)) {
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST,
MANIFEST_LOGGING_GET_MEASUREMENT_FAIL, pcr->manifest_measurement,
measurement_length);
return;
}
}
status = pcr_store_update_versioned_buffer (pcr->store, pcr->hash, pcr->manifest_measurement,
manifest_measurement, measurement_length, true, 0);
if (status != 0) {
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MANIFEST,
MANIFEST_LOGGING_RECORD_MEASUREMENT_FAIL, pcr->manifest_measurement, status);
return;
}
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, pcr->manifest_id_measurement, status);
return;
}
}
status = pcr_store_update_versioned_buffer (pcr->store, pcr->hash, pcr->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, pcr->manifest_id_measurement, status);
return;
}
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, pcr->manifest_platform_id_measurement,
status);
return;
}
}
status = pcr_store_update_versioned_buffer (pcr->store, pcr->hash,
pcr->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, pcr->manifest_platform_id_measurement,
status);
}
if (active != NULL) {
active->free_platform_id (active, platform_id);
}
}