core/firmware/firmware_pfm_verify.h (167 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#ifndef FIRMWARE_PFM_VERIFY_H_
#define FIRMWARE_PFM_VERIFY_H_
#include <stddef.h>
#include <stdint.h>
#include "attestation/pcr_store.h"
#include "crypto/hash.h"
#include "crypto/signature_verification.h"
#include "flash/flash.h"
#include "manifest/pfm/pfm.h"
#include "status/module_id.h"
/**
* Variable context for device firmware verification with a PFM.
*/
struct firmware_pfm_verify_state {
int32_t result; /**< Result of the firmware verification. */
};
/**
* Handler for device firmware that will be verified using a PFM. Loading the firmware would
* happen as a separate step by some other component, so there would still need to some additional
* type of verification on the images during the load process to prevent time-of-check/time-of-use
* issues. Using a PFM in this way mainly provides a mechanism for measurement and attestation that
* is similar to host firmware flows that use PFMs.
*
* There is no PFM management provided. It's expected that the PFM will be updated and managed as
* part of the firmware image. Since the PFM is directly bundled and managed by the firmware that
* it's verifying, there some limitations to PFM construction to fit this model:
*
* 1. Only a single version of firmware can be present in the PFM. This single entry will always
* be used for verification without any kind of version string matching that is used in the
* host firmware flows.
* 2. Only a single firmware component can be present in the PFM. The verification flow is
* intended to support one and only one firmware image on flash, which is incompatible with the
* concept of multiple independent firmware components sharing a flash.
* 3. Only images marked to be always validated will be verified. Other regions of flash will be
* ignored.
* 4. Only v2 PFMs are supported since there is no ability to provide an RSA engine as part of
* verification. PFMv1 use is generally discouraged due to the better security and easier
* manageability of PFMv2.
*/
struct firmware_pfm_verify {
struct firmware_pfm_verify_state *state; /**< Variable context for firmware verification. */
const struct flash *flash; /**< Flash device containing the firmware image. */
const struct pfm *pfm; /**< PFM to use for firmware verification. */
const struct hash_engine *hash; /**< Hash engine to use for verification. */
const struct signature_verification *sig_verify; /**< Engine for PFM verification. */
struct pcr_store *pcr; /**< PCR manager for verification measurements. */
char *version; /**< Buffer for the firmware version. */
size_t max_version; /**< Length of the firmware version buffer. */
uint16_t measurement_result; /**< Measurement ID for the verification result. */
uint16_t measurement_version; /**< Measurement ID for the firmware version string. */
uint16_t measurement_pfm; /**< Measurement ID for the PFM digest. */
uint16_t measurement_pfm_id; /**< Measurement ID for the PFM ID. */
uint16_t measurement_platform_id; /**< Measurement ID for the PFM platform ID. */
};
int firmware_pfm_verify_init (struct firmware_pfm_verify *fw_verify,
struct firmware_pfm_verify_state *state, const struct flash *flash, const struct pfm *pfm,
const struct hash_engine *hash, const struct signature_verification *sig_verify,
struct pcr_store *pcr, char *version_buffer, size_t max_version_length,
uint16_t measurement_result, uint16_t measurement_version, uint16_t measurement_pfm,
uint16_t measurement_pfm_id, uint16_t measurement_platform_id);
int firmware_pfm_verify_init_state (const struct firmware_pfm_verify *fw_verify);
void firmware_pfm_verify_release (const struct firmware_pfm_verify *fw_verify);
int firmware_pfm_verify_run_verification (const struct firmware_pfm_verify *fw_verify);
int firmware_pfm_verify_get_fw_version_measured_data (const struct firmware_pfm_verify *fw_verify,
size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len);
int firmware_pfm_verify_hash_fw_version_measured_data (const struct firmware_pfm_verify *fw_verify,
const struct hash_engine *hash);
int firmware_pfm_verify_get_pfm_digest_measured_data (const struct firmware_pfm_verify *fw_verify,
size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len);
int firmware_pfm_verify_hash_pfm_digest_measured_data (const struct firmware_pfm_verify *fw_verify,
const struct hash_engine *hash);
int firmware_pfm_verify_get_pfm_id_measured_data (const struct firmware_pfm_verify *fw_verify,
size_t offset, uint8_t *buffer, size_t length, uint32_t *total_len);
int firmware_pfm_verify_hash_pfm_id_measured_data (const struct firmware_pfm_verify *fw_verify,
const struct hash_engine *hash);
int firmware_pfm_verify_get_pfm_platform_id_measured_data (
const struct firmware_pfm_verify *fw_verify, size_t offset, uint8_t *buffer, size_t length,
uint32_t *total_len);
int firmware_pfm_verify_hash_pfm_platform_id_measured_data (
const struct firmware_pfm_verify *fw_verify, const struct hash_engine *hash);
/* Initializers for accessing the measured data of the verification. */
/**
* Statically initialize a pcr_measured_data structure for the verification result measurement.
*
* @param fw_verify_state The variable context for the firmware verification handler generating the
* measurement.
*/
#define firmware_pfm_verify_result_measured_data_init(fw_verify_state) { \
.type = PCR_DATA_TYPE_MEMORY, \
.data = { \
.memory = { \
.buffer = (uint8_t*) (&(fw_verify_state)->result), \
.length = sizeof (int32_t) \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the verified firmware version
* measurement.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_fw_version_measured_data_init(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_fw_version_measured_data, \
.hash_data = (pcr_data_hash_measured_data) \
firmware_pfm_verify_hash_fw_version_measured_data, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the verified firmware version
* measurement.
*
* The callback to retrieve the data hash will not be set.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_fw_version_measured_data_init_no_hash(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_fw_version_measured_data, \
.hash_data = NULL, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM digest measurement.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_digest_measured_data_init(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_pfm_digest_measured_data, \
.hash_data = (pcr_data_hash_measured_data) \
firmware_pfm_verify_hash_pfm_digest_measured_data, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM digest measurement.
*
* The callback to retrieve the data hash will not be set.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_digest_measured_data_init_no_hash(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_pfm_digest_measured_data, \
.hash_data = NULL, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM ID measurement.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_id_measured_data_init(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_pfm_id_measured_data, \
.hash_data = \
(pcr_data_hash_measured_data) firmware_pfm_verify_hash_pfm_id_measured_data, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM ID measurement.
*
* The callback to retrieve the data hash will not be set.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_id_measured_data_init_no_hash(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = \
(pcr_data_get_measured_data) firmware_pfm_verify_get_pfm_id_measured_data, \
.hash_data = NULL, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM platform ID measurement.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_platform_id_measured_data_init(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = (pcr_data_get_measured_data) \
firmware_pfm_verify_get_pfm_platform_id_measured_data, \
.hash_data = (pcr_data_hash_measured_data) \
firmware_pfm_verify_hash_pfm_platform_id_measured_data, \
.context = (void*) (fw_verify), \
}, \
}, \
}
/**
* Statically initialize a pcr_measured_data structure for the PFM platform ID measurement.
*
* The callback to retrieve the data hash will not be set.
*
* @param fw_verify The verification handler that is generating the measurement.
*/
#define firmware_pfm_verify_pfm_platform_id_measured_data_init_no_hash(fw_verify) { \
.type = PCR_DATA_TYPE_CALLBACK, \
.data = { \
.callback = { \
.get_data = (pcr_data_get_measured_data) \
firmware_pfm_verify_get_pfm_platform_id_measured_data, \
.hash_data = NULL, \
.context = (void*) (fw_verify), \
}, \
}, \
}
#define FIRMWARE_PFM_VERIFY_ERROR(code) ROT_ERROR (ROT_MODULE_FIRMWARE_PFM_VERIFY, code)
/**
* Error codes that can be generated by firmware image verification with a PFM.
*/
enum {
FIRMWARE_PFM_VERIFY_INVALID_ARGUMENT = FIRMWARE_PFM_VERIFY_ERROR (0x00), /**< Input parameter is null or not valid. */
FIRMWARE_PFM_VERIFY_NO_MEMORY = FIRMWARE_PFM_VERIFY_ERROR (0x01), /**< Memory allocation failed. */
FIRMWARE_PFM_VERIFY_NOT_VERIFIED = FIRMWARE_PFM_VERIFY_ERROR (0x02), /**< Firmware verification has not been run. */
FIRMWARE_PFM_VERIFY_PFM_MULTI_FW = FIRMWARE_PFM_VERIFY_ERROR (0x03), /**< The PFM contains multiple FW components. */
FIRMWARE_PFM_VERIFY_EMPTY_PFM = FIRMWARE_PFM_VERIFY_ERROR (0x04), /**< The PFM contains no firmware information. */
FIRMWARE_PFM_VERIFY_PFM_MULTI_VERSION = FIRMWARE_PFM_VERIFY_ERROR (0x05), /**< The PFM contains multiple firmware versions. */
FIRMWARE_PFM_VERIFY_PFM_NO_VERSION = FIRMWARE_PFM_VERIFY_ERROR (0x06), /**< The PFM contains no firmware version. */
FIRMWARE_PFM_VERIFY_PFM_NO_IMAGE = FIRMWARE_PFM_VERIFY_ERROR (0x07), /**< The PFM contains no firmware image information. */
};
#endif /* FIRMWARE_PFM_VERIFY_H_ */