core/cmd_interface/device_manager.h (283 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#ifndef DEVICE_MANAGER_H_
#define DEVICE_MANAGER_H_
#include <stdint.h>
#include "attestation/attestation.h"
#include "cmd_interface/device_manager_observer.h"
#include "common/certificate.h"
#include "common/observable.h"
#include "crypto/ecc.h"
#include "crypto/hash.h"
#include "crypto/rsa.h"
#include "status/rot_status.h"
// Reserved device manager table entry numbers
#define DEVICE_MANAGER_SELF_DEVICE_NUM 0
#define DEVICE_MANAGER_MCTP_BRIDGE_DEVICE_NUM 1
// Index indicating component not in PCD
#define DEVICE_MANAGER_NOT_PCD_COMPONENT 0xFF
// Maximum key length
#define DEVICE_MANAGER_MAX_KEY_LEN RSA_MAX_KEY_LENGTH
// Default minimum activity check
#define DEVICE_MANAGER_MIN_ACTIVITY_CHECK 300000
// MCTP control protocol default timeout
#define DEVICE_MANAGER_MCTP_CTRL_PROTOCOL_TIMEOUT_MS 1000
// Attestation status measurement version
#define DEVICE_MANAGER_ATTESTATION_STATUS_VERSION 2
/**
* Convert response timeout in milliseconds to timeout in 10ms multiples
*
* @param timeout Timeout value in milliseconds
*/
#define device_manager_set_timeout_ms(timeout) ((timeout) / 10)
/**
* Convert crypto response timeout in milliseconds to timeout in 100ms multiples
*
* @param timeout Timeout value in milliseconds
*/
#define device_manager_set_crypto_timeout_ms(timeout) ((timeout) / 100)
/**
* Device states
*/
enum device_manager_device_state {
DEVICE_MANAGER_AUTHENTICATED = 0x0, /**< Authenticated state */
DEVICE_MANAGER_UNIDENTIFIED, /**< Communication with device not established */
DEVICE_MANAGER_NEVER_ATTESTED, /**< Device ready for attestation start, but never attested before */
DEVICE_MANAGER_READY_FOR_ATTESTATION, /**< Device ready for attestation start */
DEVICE_MANAGER_ATTESTATION_FAILED, /**< Previous attestation attempt failed due to other error */
DEVICE_MANAGER_NOT_ATTESTABLE, /**< Not an attestable device */
DEVICE_MANAGER_AUTHENTICATED_WITHOUT_CERTS, /**< Authenticated without certs */
DEVICE_MANAGER_AUTHENTICATED_WITH_TIMEOUT, /**< Autenticated with timeout */
DEVICE_MANAGER_AUTHENTICATED_WITHOUT_CERTS_WITH_TIMEOUT, /**< Autenticated without certs with timeout */
DEVICE_MANAGER_ATTESTATION_INTERRUPTED, /**< Communication with device is interrupted */
DEVICE_MANAGER_ATTESTATION_INVALID_VERSION = 0x10, /**< Previous attestation attempt failed due to invalid version */
DEVICE_MANAGER_ATTESTATION_INVALID_CAPS, /**< Previous attestation attempt failed due to invalid capabilities */
DEVICE_MANAGER_ATTESTATION_INVALID_ALGORITHM, /**< Previous attestation attempt failed due to invalid algorithm */
DEVICE_MANAGER_ATTESTATION_INVALID_DIGESTS, /**< Previous attestation attempt failed due to invalid digests */
DEVICE_MANAGER_ATTESTATION_INVALID_CERTS, /**< Previous attestation attempt failed due to invalid certificates */
DEVICE_MANAGER_ATTESTATION_INVALID_CHALLENGE, /**< Previous attestation attempt failed due to invalid challenge */
DEVICE_MANAGER_ATTESTATION_INVALID_MEASUREMENT, /**< Previous attestation attempt failed due to invalid measurement */
DEVICE_MANAGER_ATTESTATION_INVALID_RESPONSE, /**< Communication with device is unexpected */
DEVICE_MANAGER_ATTESTATION_MEASUREMENT_MISMATCH = 0x20, /**< Previous attestation attempt failed due to measurement mismatch */
DEVICE_MANAGER_ATTESTATION_UNTRUSTED_CERTS, /**< Previous attestation attempt failed due to untrusted certificates */
DEVICE_MANAGER_ATTESTATION_INVALID_CFM, /**< Previous attestation attempt failed due to invalid CFM */
MAX_DEVICE_MANAGER_STATES, /**< Max number of device states */
};
/**
* Device hierarchy roles as defined in the Cerberus protocol.
*/
enum {
DEVICE_MANAGER_AC_ROT_MODE = 0, /**< Device acting as AC-RoT */
DEVICE_MANAGER_PA_ROT_MODE, /**< Device acting as PA-RoT */
NUM_BUS_HIERACHY_ROLES, /**< Number of hierarchy roles */
};
/**
* Roles a device supports on the I2C bus as defined in the Cerberus protocol.
*/
enum {
DEVICE_MANAGER_UNKNOWN_BUS_ROLE = 0, /**< Unknown bus role */
DEVICE_MANAGER_MASTER_BUS_ROLE, /**< Device acting as bus master */
DEVICE_MANAGER_SLAVE_BUS_ROLE, /**< Device acting as bus slave */
DEVICE_MANAGER_MASTER_AND_SLAVE_BUS_ROLE, /**< Device acting as both master and slave on bus */
NUM_BUS_ROLES, /**< Number of bus roles */
};
/**
* Channel security capabilities of the device as defined in the Cerberus protocol.
*/
enum {
DEVICE_MANAGER_SECURITY_NONE = 0, /**< No channel security. */
DEVICE_MANAGER_SECURITY_HASH_KDF = 1, /**< Channel supports using hash/KDF. */
DEVICE_MANAGER_SECURITY_AUTHENTICATION = 2, /**< Channel support certificate authentication. */
DEVICE_MANAGER_SECURITY_CONFIDENTIALITY = 4, /**< Channel support AES encryption. */
};
/**
* Supported ECC key strength as defined in the Cerberus protocol.
*/
enum {
DEVICE_MANAGER_ECC_KEY_NONE = 0, /**< No ECC key support. */
DEVICE_MANAGER_ECC_KEY_160 = 1, /**< Supports ECC-160. */
DEVICE_MANAGER_ECC_KEY_256 = 2, /**< Supports ECC-256. */
DEVICE_MANAGER_ECC_KEY_RESERVED = 4, /**< Unused. */
};
/**
* Supported RSA key strength as defined in the Cerberus protocol.
*/
enum {
DEVICE_MAANGER_RSA_KEY_NONE = 0, /**< No RSA key support. */
DEVICE_MANAGER_RSA_KEY_2048 = 1, /**< Supports RSA-2048. */
DEVICE_MANAGER_RSA_KEY_3072 = 2, /**< Supports RSA-3072. */
DEVICE_MANAGER_RSA_KEY_4096 = 4, /**< Supports RSA-4096. */
};
/**
* Supported AES key strength as defined in the Cerberus protocol.
*/
enum {
DEVICE_MANAGER_AES_KEY_NONE = 0, /**< No AES key support. */
DEVICE_MANAGER_AES_KEY_128 = 1, /**< Supports AES-128. */
DEVICE_MANAGER_AES_KEY_256 = 2, /**< Supports AES-256. */
DEVICE_MANAGER_AES_KEY_384 = 4, /**< Supports AES-384. */
};
#pragma pack(push, 1)
/**
* Container for a device's capabilities. This matches the Cerberus protocol request format.
*/
struct device_manager_capabilities {
uint16_t max_message_size; /**< Maximum message payload the device can accept */
uint16_t max_packet_size; /**< Maximum packet payload the device can accept */
uint8_t security_mode:3; /**< Security mode */
uint8_t reserved1:1; /**< Reserved */
uint8_t bus_role:2; /**< Master/Slave role enabled */
uint8_t hierarchy_role:2; /**< AC-RoT or PA-RoT */
uint8_t reserved2:5; /**< Reserved */
uint8_t fw_protection:1; /**< FW protection enabled */
uint8_t policy_support:1; /**< Policy support enabled */
uint8_t pfm_support:1; /**< PFM support enabled */
uint8_t rsa_key_strength:3; /**< RSA key strength */
uint8_t ecc_key_strength:3; /**< ECC key strength */
uint8_t ecdsa:1; /**< ECDSA capable */
uint8_t rsa:1; /**< RSA capable */
uint8_t aes_enc_key_strength:3; /**< AES encryption key strength */
uint8_t reserved3:4; /**< Reserved */
uint8_t ecc:1; /**< ECC encryption capable */
};
/**
* Container for all of a device's capabilities. This matches the Cerberus protocol response
* format.
*/
struct device_manager_full_capabilities {
struct device_manager_capabilities request; /**< Capabilities request information. */
uint8_t max_timeout; /**< Maximum timeout in 10ms multiples. */
uint8_t max_sig; /**< Maximum cryptographic response delay in 100ms multiples. */
};
#pragma pack(pop)
/**
* Container holding public key
*/
struct device_manager_key {
uint8_t key[DEVICE_MANAGER_MAX_KEY_LEN]; /**< Buffer with public key */
size_t key_len; /**< Length of key in buffer */
int key_type; /**< Key type */
};
#pragma pack(push, 1)
/**
* Container for device manager attestation event counters
*/
struct device_manager_attestation_summary_event_counters {
uint16_t status_success_count; /* Number of successful attestations */
uint16_t status_success_timeout_count; /* Number of successful attestations with timeout */
uint16_t status_fail_internal_count; /* Number of failed attestations due to internal error */
uint16_t status_fail_timeout_count; /* Number of failed attestations due to timeout */
uint16_t status_fail_invalid_response_count; /* Number of failed attestations due to invalid response */
uint16_t status_fail_invalid_config_count; /* Number of failed attestations due to invalid configuration */
};
/**
* Container for device manager attestation summary
*/
struct device_manager_attestation_summary {
uint8_t prev_state; /* Previous attestation state */
struct device_manager_attestation_summary_event_counters event_counters; /* Attestation event counters */
};
#pragma pack(pop)
/**
* Entry type in a device manager table
*/
struct device_manager_entry {
struct device_manager_full_capabilities capabilities; /**< Device capabilities */
platform_clock attestation_timeout; /**< Clock tracking when device should be attested */
uint32_t component_id; /**< Component ID in PCD and CFM */
enum device_manager_device_state state; /**< Device state */
struct device_manager_attestation_summary summary; /**< Attestation summary data */
uint16_t pci_vid; /**< PCI Vendor ID */
uint16_t pci_device_id; /**< PCI Device ID */
uint16_t pci_subsystem_vid; /**< PCI Subsystem Vendor ID */
uint16_t pci_subsystem_id; /**< PCI Subsystem ID */
uint8_t slot_num; /**< Device certificate chain slot number */
uint8_t smbus_addr; /**< SMBUS address */
uint8_t eid; /**< Endpoint ID */
uint8_t pcd_component_index; /**< Index of component in PCD */
};
/**
* Entry type in an unidentified device manager linked list
*/
struct device_manager_unidentified_entry {
platform_clock discovery_timeout; /**< Clocking tracking when device should be discovered */
bool timeout; /**< Flag indicating if last discovery timed out */
uint8_t eid; /**< Endpoint ID */
struct device_manager_unidentified_entry *next; /**< Next entry in circular linked list */
};
/**
* Module which holds a table of all devices Cerberus expects to communicate with and itself, to be
* populated from PCD
*/
struct device_manager {
struct device_manager_entry *entries; /**< Device table entries. */
uint8_t *attestation_status; /**< Dynamically allocated buffer to hold attestation status of all attestable devices. */
uint8_t num_devices; /**< Number of device table entries. */
uint8_t num_requester_devices; /**< Number of requester device table entries. */
uint8_t num_unique_responder_devices; /**< Number of unique responder device table entries. */
uint8_t num_responder_devices; /**< Number of responder device table entries. */
uint8_t last_device_authenticated; /**< Device number of last device authenticated. */
uint32_t unauthenticated_cadence_ms; /**< Period to wait before reauthenticating unauthenticated device. */
uint32_t authenticated_cadence_ms; /**< Period to wait before reauthenticating authenticated device. */
uint32_t unidentified_timeout_ms; /**< Timeout period to wait before reidentifying unidentified device. */
uint32_t mctp_ctrl_timeout_ms; /**< Timeout duration for MCTP control requests. */
uint32_t mctp_bridge_additional_timeout_ms; /**< Timeout adjustment to MCTP bridge communication. */
uint32_t attestation_rsp_not_ready_max_duration_ms; /**< Maximum SPDM ResponseNotReady duration. */
uint8_t attestation_rsp_not_ready_max_retry; /**< Maximum SPDM ResponseNotReady retries. */
bool attestable_components_list_invalid; /**< Flag indicating we failed to correctly load components from PCD. */
#ifdef ATTESTATION_SUPPORT_DEVICE_DISCOVERY
struct device_manager_unidentified_entry *unidentified; /**< Unidentified device circular linked list. */
#endif
size_t hash_len; /**< Length of certificate chain hash */
uint8_t cert_chain_digest[HASH_MAX_HASH_LEN]; /**< Device certificate chain digest */
uint8_t cert_chain_digest_eid; /*< EID of component digest belongs */
struct device_manager_key alias_key; /**< Container with device alias key */
uint8_t alias_key_eid; /**< EID of component alias key belongs */
struct observable observable; /**< Observer manager for the interface. */
};
int device_manager_init (struct device_manager *mgr, int num_requester_devices,
int num_unique_responder_devices, int num_responder_devices, uint8_t hierarchy,
uint8_t bus_role, uint32_t unauthenticated_cadence_ms, uint32_t authenticated_cadence_ms,
uint32_t unidentified_timeout_ms, uint32_t mctp_ctrl_timeout_ms,
uint32_t mctp_bridge_additional_timeout_ms, uint32_t attestation_rsp_not_ready_max_duration_ms,
uint8_t attestation_rsp_not_ready_max_retry);
int device_manager_init_ac_rot (struct device_manager *mgr, int num_requester_devices,
uint8_t bus_role);
void device_manager_release (struct device_manager *mgr);
int device_manager_add_observer (struct device_manager *mgr,
struct device_manager_observer *observer);
int device_manager_remove_observer (struct device_manager *mgr,
struct device_manager_observer *observer);
int device_manager_get_device_num (struct device_manager *mgr, uint8_t eid);
int device_manager_get_device_num_by_component (struct device_manager *mgr, uint32_t component_id,
uint8_t component_instance);
int device_manager_get_device_addr (struct device_manager *mgr, int device_num);
int device_manager_get_device_addr_by_eid (struct device_manager *mgr, uint8_t eid);
int device_manager_get_device_eid (struct device_manager *mgr, int device_num);
int device_manager_update_device_eid (struct device_manager *mgr, int device_num, uint8_t eid);
int device_manager_update_not_attestable_device_entry (struct device_manager *mgr, int device_num,
uint8_t eid, uint8_t smbus_addr, uint8_t pcd_component_index);
int device_manager_update_mctp_bridge_device_entry (struct device_manager *mgr, int device_num,
uint16_t pci_vid, uint16_t pci_device_id, uint16_t pci_subsystem_vid, uint16_t pci_subsystem_id,
uint8_t components_count, uint32_t component_id, uint8_t pcd_component_index);
int device_manager_get_device_capabilities (struct device_manager *mgr, int device_num,
struct device_manager_full_capabilities *capabilities);
int device_manager_update_device_capabilities (struct device_manager *mgr, int device_num,
struct device_manager_full_capabilities *capabilities);
int device_manager_get_device_capabilities_request (struct device_manager *mgr,
struct device_manager_capabilities *capabilites);
int device_manager_update_device_capabilities_request (struct device_manager *mgr, int device_num,
struct device_manager_capabilities *capabilities);
size_t device_manager_get_max_message_len (struct device_manager *mgr, int device_num);
size_t device_manager_get_max_message_len_by_eid (struct device_manager *mgr, uint8_t eid);
size_t device_manager_get_max_transmission_unit (struct device_manager *mgr, int device_num);
size_t device_manager_get_max_transmission_unit_by_eid (struct device_manager *mgr, uint8_t eid);
uint32_t device_manager_get_reponse_timeout (struct device_manager *mgr, int device_num);
uint32_t device_manager_get_reponse_timeout_by_eid (struct device_manager *mgr, uint8_t eid);
uint32_t device_manager_get_crypto_timeout (struct device_manager *mgr, int device_num);
uint32_t device_manager_get_crypto_timeout_by_eid (struct device_manager *mgr, uint8_t eid);
int device_manager_get_rsp_not_ready_limits (struct device_manager *mgr, uint32_t *max_timeout_ms,
uint8_t *max_retries);
uint32_t device_manager_get_mctp_ctrl_timeout (struct device_manager *mgr);
int device_manager_update_cert_chain_digest (struct device_manager *mgr, uint8_t eid,
uint8_t slot_num, const uint8_t *buf, size_t buf_len);
int device_manager_clear_cert_chain_digest (struct device_manager *mgr, uint8_t eid);
int device_manager_compare_cert_chain_digest (struct device_manager *mgr, uint8_t eid,
const uint8_t *digest, size_t digest_len);
int device_manager_update_alias_key (struct device_manager *mgr, uint8_t eid, const uint8_t *key,
size_t key_len, int key_type);
const struct device_manager_key* device_manager_get_alias_key (struct device_manager *mgr,
uint8_t eid);
int device_manager_clear_alias_key (struct device_manager *mgr, uint8_t eid);
int device_manager_get_device_state (struct device_manager *mgr, int device_num);
int device_manager_get_device_state_by_eid (struct device_manager *mgr, uint8_t eid);
int device_manager_update_device_state (struct device_manager *mgr, int device_num,
enum device_manager_device_state state);
int device_manager_update_device_state_by_eid (struct device_manager *mgr, uint8_t eid,
enum device_manager_device_state state);
int device_manager_get_attestation_summary_prev_state (struct device_manager *mgr, int device_num);
int device_manager_get_attestation_summary_prev_state_by_eid (struct device_manager *mgr,
uint8_t eid);
int device_manager_update_attestation_summary_prev_state (struct device_manager *mgr,
int device_num);
int device_manager_update_attestation_summary_prev_state_by_eid (struct device_manager *mgr,
uint8_t eid);
int device_manager_get_attestation_summary_event_counters (struct device_manager *mgr,
int device_num, struct device_manager_attestation_summary_event_counters *event_counters);
int device_manager_get_attestation_summary_event_counters_by_eid (struct device_manager *mgr,
uint8_t eid, struct device_manager_attestation_summary_event_counters *event_counters);
int device_manager_update_attestation_summary_event_counters (struct device_manager *mgr,
int device_num);
int device_manager_update_attestation_summary_event_counters_by_eid (struct device_manager *mgr,
uint8_t eid);
int device_manager_get_eid_of_next_device_to_attest (struct device_manager *mgr);
int device_manager_reset_authenticated_devices (struct device_manager *mgr);
int device_manager_reset_discovered_devices (struct device_manager *mgr);
int device_manager_get_component_id (struct device_manager *mgr, uint8_t eid,
uint32_t *component_id);
int device_manager_get_device_num_by_device_ids (struct device_manager *mgr, uint16_t pci_vid,
uint16_t pci_device_id, uint16_t pci_subsystem_vid, uint16_t pci_subsystem_id);
int device_manager_update_device_ids (struct device_manager *mgr, int device_num, uint16_t pci_vid,
uint16_t pci_device_id, uint16_t pci_subsystem_vid, uint16_t pci_subsystem_id);
#ifdef ATTESTATION_SUPPORT_DEVICE_DISCOVERY
void device_manager_clear_unidentified_devices (struct device_manager *mgr);
int device_manager_add_unidentified_device (struct device_manager *mgr, uint8_t eid);
int device_manager_remove_unidentified_device (struct device_manager *mgr, uint8_t eid);
int device_manager_unidentified_device_timed_out (struct device_manager *mgr, uint8_t eid);
int device_manager_get_eid_of_next_device_to_discover (struct device_manager *mgr);
#endif
uint32_t device_manager_get_time_till_next_action (struct device_manager *mgr);
int device_manager_get_attestation_status (struct device_manager *mgr,
const uint8_t **attestation_status);
int device_manager_mark_component_attestation_invalid (struct device_manager *mgr);
bool device_manager_is_device_unattestable (struct device_manager *mgr, uint8_t eid);
#define DEVICE_MGR_ERROR(code) ROT_ERROR (ROT_MODULE_DEVICE_MANAGER, code)
/**
* Error codes that can be generated by the device manager.
*/
enum {
DEVICE_MGR_INVALID_ARGUMENT = DEVICE_MGR_ERROR (0x00), /**< Input parameter is null or not valid. */
DEVICE_MGR_NO_MEMORY = DEVICE_MGR_ERROR (0x01), /**< Memory allocation failed. */
DEVICE_MGR_UNKNOWN_DEVICE = DEVICE_MGR_ERROR (0x02), /**< Invalid device number. */
DEVICE_MGR_INVALID_CERT_NUM = DEVICE_MGR_ERROR (0x03), /**< Invalid certificate number. */
DEVICE_MGR_BUF_TOO_SMALL = DEVICE_MGR_ERROR (0x04), /**< Provided buffer too small for output. */
DEVICE_MGR_INPUT_TOO_LARGE = DEVICE_MGR_ERROR (0x05), /**< Provided data larger than storage buffer. */
DEVICE_MGR_DIGEST_LEN_MISMATCH = DEVICE_MGR_ERROR (0x06), /**< Provided digest not same length as cached digest. */
DEVICE_MGR_DIGEST_MISMATCH = DEVICE_MGR_ERROR (0x07), /**< Provided digest not same as cached digest. */
DEVICE_MGR_NO_DEVICES_AVAILABLE = DEVICE_MGR_ERROR (0x08), /**< No devices ready for attestation. */
DEVICE_MGR_DIGEST_NOT_UNIQUE = DEVICE_MGR_ERROR (0x09), /**< Certificate chain digest not unique. */
DEVICE_MGR_INVALID_RESPONDER_COUNT = DEVICE_MGR_ERROR (0x0A), /**< Invalid responder count. */
};
#endif /* DEVICE_MANAGER_H_ */