core/manifest/manifest_manager.c (188 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #include <string.h> #include "manifest_manager.h" #include "platform_api.h" #include "common/buffer_util.h" #include "common/common_math.h" /** * Initialize the manifest manager. * * @param manager The manager to initialize. * @param hash The hash engine to generate measurement data. * * @return 0 if the manifest manager was initialized successfully or an error code. */ int manifest_manager_init (struct manifest_manager *manager, const struct hash_engine *hash) { if ((manager == NULL) || (hash == NULL)) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } manager->port = 0; manager->hash = hash; return 0; } /** * Set the port identifier for a manifest manager. * * @param host The manifest manager to configure. * @param port The port identifier to set. */ void manifest_manager_set_port (struct manifest_manager *manager, int port) { if (manager) { manager->port = port; } } /** * Get the port identifier for a manifest manager. * * @param host The manifest manager instance to query. * * @return The port identifier or an error code. Use ROT_IS_ERROR to check for errors. */ int manifest_manager_get_port (const struct manifest_manager *manager) { if (manager) { if (manager->port < 0) { return 0; } else { return manager->port; } } else { return MANIFEST_MANAGER_INVALID_ARGUMENT; } } /** * Get the data used for the manifest digest measurement. * * @param active The manifest to query * @param hash Hash engine to use for manifest digest calculation. * @param offset The offset to read data from. * @param buffer The output buffer to be filled with measured data. * @param length Maximum length of the buffer. * @param total_len Output buffer with total length of measured data. This will contain the total * length of the measurement even if only partially returned. * * @return Length of the measured data if successfully retrieved or an error code. */ int manifest_manager_get_manifest_digest_measured_data (const struct manifest *active, const struct hash_engine *hash, size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len) { uint8_t hash_out[SHA512_HASH_LENGTH] = {0}; int hash_length = SHA256_HASH_LENGTH; if ((hash == NULL) || (buffer == NULL) || (total_len == NULL)) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } if (active) { hash_length = active->get_hash (active, hash, hash_out, sizeof (hash_out)); if (ROT_IS_ERROR (hash_length)) { return hash_length; } } *total_len = hash_length; return buffer_copy (hash_out, hash_length, &offset, &length, buffer); } /** * Update a hash context with the data used for the manifest digest measurement. * * The two hash engines must be different instances. * * @param active The manifest to query. * @param manifest_hash Hash engine to use for manifest digest calculation. * @param measure_hash Hash engine to update with the measured data. * * @return 0 if the hash was updated successfully or an error code. */ int manifest_manager_hash_manifest_digest_measured_data (const struct manifest *active, const struct hash_engine *manifest_hash, const struct hash_engine *measure_hash) { uint8_t hash_out[SHA512_HASH_LENGTH] = {0}; int hash_length = SHA256_HASH_LENGTH; if ((manifest_hash == NULL) || (measure_hash == NULL)) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } if (manifest_hash == measure_hash) { return MANIFEST_MANAGER_SAME_HASH_ENGINE; } if (active) { hash_length = active->get_hash (active, manifest_hash, hash_out, sizeof (hash_out)); if (ROT_IS_ERROR (hash_length)) { return hash_length; } } return measure_hash->update (measure_hash, hash_out, hash_length); } /** * Generate the data for the manifest ID measurement. * * @param active The manifest to query. * @param id Output for the ID. This must be 5 bytes long. * * @return 0 if the ID was retrieved successfully or an error code. */ static int manifest_manager_construct_id_measurement_data (const struct manifest *active, uint8_t *id) { int status; if (active) { id[0] = 1; status = active->get_id (active, (uint32_t*) &id[1]); if (status != 0) { return status; } } else { memset (id, 0, 5); } return 0; } /** * Get the data used for the manifest ID measurement. * * @param active The manifest to query. * @param offset The offset to read data from. * @param buffer The output buffer to be filled with measured data. * @param length Maximum length of the buffer. * @param total_len Output buffer with total length of manifest ID measurement. This should * contain total length of the measurement even if only partially returned. * * @return Length of the measured data if successfully retrieved or an error code. */ int manifest_manager_get_id_measured_data (const struct manifest *active, size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len) { uint8_t id[5]; size_t id_length = sizeof (id); int status; if ((buffer == NULL) || (total_len == NULL)) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } *total_len = id_length; status = manifest_manager_construct_id_measurement_data (active, id); if (status != 0) { return status; } return buffer_copy (id, id_length, &offset, &length, buffer); } /** * Update a hash context with the data used for the manifest ID measurement. * * @param active The manifest to query. * @param hash Hash engine to update. * * @return 0 if the hash was updated successfully or an error code. */ int manifest_manager_hash_id_measured_data (const struct manifest *active, const struct hash_engine *hash) { uint8_t id[5]; int status; if (hash == NULL) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } status = manifest_manager_construct_id_measurement_data (active, id); if (status != 0) { return status; } return hash->update (hash, id, sizeof (id)); } /** * Get the data used for the manifest platform ID measurement. * * @param active The manifest to query * @param offset The offset to read data from * @param buffer The output buffer to be filled with measured data * @param length Maximum length of the buffer * @param total_len Output buffer with total length of platform ID measurement. This should * contain total length of the measurement even if only partially returned. * * @return Length of the measured data if successfully retrieved or an error code. */ int manifest_manager_get_platform_id_measured_data (const struct manifest *active, size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len) { char *id = NULL; size_t id_length; size_t bytes_read; char empty_string = '\0'; int status; if ((buffer == NULL) || (total_len == NULL)) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } if (active) { status = active->get_platform_id (active, &id, 0); if (status != 0) { return status; } id_length = strlen (id) + 1; } else { id = &empty_string; id_length = 1; } *total_len = id_length; bytes_read = buffer_copy ((uint8_t*) id, id_length, &offset, &length, buffer); if (active) { active->free_platform_id (active, id); } return bytes_read; } /** * Update a hash context with the data used for the manifest platform ID measurement. * * @param active The manifest to query. * @param hash Hash engine to update. * * @return 0 if the hash was updated successfully or an error code. */ int manifest_manager_hash_platform_id_measured_data (const struct manifest *active, const struct hash_engine *hash) { char *id = NULL; char empty_string = '\0'; int status; if (hash == NULL) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } if (active) { status = active->get_platform_id (active, &id, 0); if (status != 0) { return status; } } else { id = &empty_string; } status = hash->update (hash, (uint8_t*) id, strlen (id) + 1); if (active) { active->free_platform_id (active, id); } return status; } /** * Get the data used for the manifest measurement. * * This is functionally the same as manifest_manager_get_manifest_digest_measured_data but uses a * manifest_manager instance for the necessary hash engine. * * @param manager The manifest manager instance to query. * @param active The manifest to query * @param offset The offset to read data from * @param buffer The output buffer to be filled with measured data * @param length Maximum length of the buffer * @param total_len Output buffer with total length of measured data. This should contain total * length of the measurement even if only partially returned. * * @return Length of the measured data if successfully retrieved or an error code. */ int manifest_manager_get_manifest_measured_data (const struct manifest_manager *manager, const struct manifest *active, size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len) { if (manager == NULL) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } return manifest_manager_get_manifest_digest_measured_data (active, manager->hash, offset, buffer, length, total_len); } /** * Update a hash context with the data used for the manifest measurement. * * This is functionally the same as manifest_manager_hash_manifest_digest_measured_data but uses a * manifest_manager instance for the necessary hash engine. * * NOTE: The hash context contained in the manifest manager must be different from the one passed * into this function as an argument. * * @param manager The manifest manager instance to query. * @param active The manifest to query. * @param hash Hash engine to update. This must be different from the hash engined contained in the * manifest manager. * * @return 0 if the hash was updated successfully or an error code. */ int manifest_manager_hash_manifest_measured_data (const struct manifest_manager *manager, const struct manifest *active, const struct hash_engine *hash) { if (manager == NULL) { return MANIFEST_MANAGER_INVALID_ARGUMENT; } return manifest_manager_hash_manifest_digest_measured_data (active, manager->hash, hash); }