|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_ | 
|  | #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_ | 
|  |  | 
|  | /** | 
|  | * @file | 
|  | * @brief <a href="/hw/ip/keymgr/doc/">Key Manager</a> Device Interface | 
|  | * Functions | 
|  | */ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "sw/device/lib/base/macros.h" | 
|  | #include "sw/device/lib/base/mmio.h" | 
|  | #include "sw/device/lib/dif/dif_base.h" | 
|  |  | 
|  | #include "sw/device/lib/dif/autogen/dif_keymgr_autogen.h" | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif  // __cplusplus | 
|  |  | 
|  | /** | 
|  | * A typical usage of this library during different secure boot | 
|  | * stages is as follows: | 
|  | * | 
|  | * - In ROM: | 
|  | *   - Create a new handle: `dif_keymgr_init()`. | 
|  | *   - Configure hardware: `dif_keymgr_configure()`. | 
|  | *   - Initialize state: `dif_keymgr_advance_state()`, | 
|  | *   `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`. | 
|  | *   - Advance state: `dif_keymgr_advance_state()`, | 
|  | *     `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`. | 
|  | * - In subsequent boot stages, i.e. ROM_EXT, BL0, kernel: | 
|  | *   - Create a new handle: `dif_keymgr_init()`. | 
|  | *   - Generate keys and/or identity seeds: | 
|  | *     `dif_keymgr_generate_versioned_key()`, | 
|  | *     `dif_keymgr_generate_identity_seed()`, `dif_keymgr_get_status_codes()`. | 
|  | *   - Read output (if applicable): `dif_keymgr_read_output()`. | 
|  | *   - Advance state: `dif_keymgr_advance_state()`, | 
|  | *     `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`. | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * Enumeration for side load slot clearing. | 
|  | */ | 
|  | typedef enum dif_keymgr_sideload_clr { | 
|  | kDifKeyMgrSideLoadClearNone = 0, | 
|  | kDifKeyMgrSideLoadClearAes = 1, | 
|  | kDifKeyMgrSideLoadClearKmac = 2, | 
|  | kDifKeyMgrSideLoadClearOtbn = 3, | 
|  | // Using different value than those enumerated above should clear all slots, | 
|  | // so we can use the mask value of this field to denote ALL case. This was | 
|  | // we can statically assert this value on the .c side of this DIF. | 
|  | kDifKeyMgrSideLoadClearAll = 7, | 
|  | } dif_keymgr_sideload_clr_t; | 
|  |  | 
|  | /** | 
|  | * Runtime configuration for key manager. | 
|  | * | 
|  | * This struct describes runtime information for one-time configuration of the | 
|  | * hardware. | 
|  | */ | 
|  | typedef struct dif_keymgr_config { | 
|  | /** | 
|  | * Number of key manager cycles before the entropy is reseeded. | 
|  | * | 
|  | * Key manager uses random values generated by the entropy source for | 
|  | * initializing its state and clearing sideload keys. This value determines | 
|  | * the frequency at which this random value is updated. | 
|  | */ | 
|  | uint16_t entropy_reseed_interval; | 
|  | } dif_keymgr_config_t; | 
|  |  | 
|  | /** | 
|  | * Key manager states. | 
|  | * | 
|  | * Key manager has seven states that control its operation. During secure boot, | 
|  | * key manager transitions between these states sequentially and these | 
|  | * transitions are irreversible until a power cycle. | 
|  | * | 
|  | * The secret value of key manager changes at each state transition in a | 
|  | * well-defined manner, thus its meaning is tied to the current state of key | 
|  | * manager. | 
|  | * | 
|  | * The functionality of key manager is directly tied to the life cycle | 
|  | * controller peripheral and it is explicitly disabled during specific life | 
|  | * cycle stages. If key manager has not been initialized, it cannot be | 
|  | * initialized until it is enabled by life cycle controller. If key manager is | 
|  | * disabled by life cycle controller while it is in an operational state, it | 
|  | * immediately wipes its contents and transitions to Disabled state. | 
|  | */ | 
|  | typedef enum dif_keymgr_state { | 
|  | /** | 
|  | * Reset state. | 
|  | * | 
|  | * This is the initial state of key manager after PoR. At this state, the | 
|  | * secret value of key manager is non-deterministic, i.e. some value based on | 
|  | * the physical characteristics of the device and environment conditions. | 
|  | */ | 
|  | kDifKeymgrStateReset, | 
|  | /** | 
|  | * Initialized state. | 
|  | * | 
|  | * Secret value of key manager is initialized with random values generated by | 
|  | * the entropy source. This is not an operational state and the key manager | 
|  | * state must be advanced one more time before keys or identity seeds can be | 
|  | * generated. | 
|  | */ | 
|  | kDifKeymgrStateInitialized, | 
|  | /** | 
|  | * CreatorRootKey state. | 
|  | * | 
|  | * This is the first operational state of key manager. At this state, key | 
|  | * manager can generate a versioned creator key or a creator identity seed | 
|  | * that can be used to generate a creator identity using an asymmetric KDF. | 
|  | */ | 
|  | kDifKeymgrStateCreatorRootKey, | 
|  | /** | 
|  | * OwnerIntermediateKey state. | 
|  | * | 
|  | * This is the second operational state of key manager. At this state, key | 
|  | * manager can generate a versioned intermediate owner key or an intermediate | 
|  | * owner identity seed that can be used to generate an intermediate owner | 
|  | * identity using an asymmetric KDF. | 
|  | */ | 
|  | kDifKeymgrStateOwnerIntermediateKey, | 
|  | /** | 
|  | * OwnerRootKey state. | 
|  | * | 
|  | * This is the last operational state of key manager. At this state, key | 
|  | * manager can generate a versioned owner key or an owner identity seed that | 
|  | * can be used to generate an owner identity using an asymmetric KDF. | 
|  | */ | 
|  | kDifKeymgrStateOwnerRootKey, | 
|  | /** | 
|  | * Disabled state. | 
|  | * | 
|  | * This is a terminal state where key manager is no longer operational. At | 
|  | * this state, the secret value of key manager is a random value. | 
|  | */ | 
|  | kDifKeymgrStateDisabled, | 
|  | /** | 
|  | * Invalid state. | 
|  | * | 
|  | * Keymgr is in an invalid state and must be reset. | 
|  | */ | 
|  | kDifKeymgrStateInvalid, | 
|  | } dif_keymgr_state_t; | 
|  |  | 
|  | /** | 
|  | * Configures key manager with runtime information. | 
|  | * | 
|  | * This function should need to be called once for the lifetime of `keymgr`. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param config Runtime configuration parameters. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_configure(const dif_keymgr_t *keymgr, | 
|  | dif_keymgr_config_t config); | 
|  |  | 
|  | /** | 
|  | * Parameters for a key manager state. | 
|  | */ | 
|  | typedef struct dif_keymgr_state_params { | 
|  | /** | 
|  | * This value is used by key manager to derive secret values and can be either | 
|  | * a value that represents the contents of a boot stage, e.g. a (truncated) | 
|  | * hash, or a tag. | 
|  | * | 
|  | * If it is a hash, changes in a boot stage will change the secret value, and | 
|  | * consequently the versioned keys and identity seeds generated at subsequent | 
|  | * boot stages. If it is a tag, those secret values, versioned keys, and | 
|  | * identity seeds will be preserved across updates of the boot stage as long | 
|  | * as the tag remains the same. | 
|  | */ | 
|  | uint32_t binding_value[8]; | 
|  |  | 
|  | /** | 
|  | * Maximum allowed version for keys generated at a state. | 
|  | */ | 
|  | uint32_t max_key_version; | 
|  | } dif_keymgr_state_params_t; | 
|  |  | 
|  | /** | 
|  | * Advances key manager state. | 
|  | * | 
|  | * This function instructs key manager to transition to the next state, i.e. | 
|  | * Reset -> Initialized -> CreatorRootKey -> OwnerIntermediateKey -> | 
|  | * OwnerRootKey -> Disabled. Once a state transition starts, key manager locks | 
|  | * the control register until the transition is complete. State transitions are | 
|  | * irreversible until a power cycle. | 
|  | * | 
|  | * The entropy source must be initialized before this function is called. After | 
|  | * PoR, key manager is in Reset state with a non-deterministic secret value. The | 
|  | * first call to this function after PoR causes key manager to initialize its | 
|  | * secret value using the random values generated by the entropy source and | 
|  | * transition to Initialized state. | 
|  | * | 
|  | * `params` is required when the next state is an operational state, | 
|  | * i.e. `CreatorRootKey`, `OwnerIntermediateKey`, or `OwnerRootKey`. It must be | 
|  | * `NULL` for all other cases. | 
|  | * | 
|  | * This is an asynchronous function because key manager state transitions | 
|  | * involve KMAC operations that can take some time to complete. Clients must | 
|  | * check the status of key manager using `dif_keymgr_get_status_codes()` before | 
|  | * calling other functions in this library. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param params The binding and max key version value for the next state. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_advance_state(const dif_keymgr_t *keymgr, | 
|  | const dif_keymgr_state_params_t *params); | 
|  |  | 
|  | /** | 
|  | * Advances key manager state without setting any of the required inputs. | 
|  | * | 
|  | * This function instructs key manager to transition to the next state, i.e. | 
|  | * Reset -> Initialized -> CreatorRootKey -> OwnerIntermediateKey -> | 
|  | * OwnerRootKey -> Disabled. Once a state transition starts, key manager locks | 
|  | * the control register until the transition is complete. State transitions are | 
|  | * irreversible until a power cycle. | 
|  | * | 
|  | * This function does not have a `dif_keymgr_state_params_t` parameter since | 
|  | * these inputs are expected to be set before this function is called, e.g. when | 
|  | * the chip is using `rom` as opposed to `test_rom`. See | 
|  | * `dif_keymgr_advance_state()` if you need to set the binding value and max key | 
|  | * version before advancing the state. | 
|  | * | 
|  | * The entropy source must be initialized before this function is called. After | 
|  | * PoR, key manager is in Reset state with a non-deterministic secret value. The | 
|  | * first call to this function after PoR causes key manager to initialize its | 
|  | * secret value using the random values generated by the entropy source and | 
|  | * transition to Initialized state. | 
|  | * | 
|  | * This is an asynchronous function because key manager state transitions | 
|  | * involve KMAC operations that can take some time to complete. Clients must | 
|  | * check the status of key manager using `dif_keymgr_get_status_codes()` before | 
|  | * calling other functions in this library. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_advance_state_raw(const dif_keymgr_t *keymgr); | 
|  |  | 
|  | /** | 
|  | * Disables key manager. | 
|  | * | 
|  | * This function disables key manager until the next power cycle by making it | 
|  | * transition to Disabled state. Disabled state is a terminal state where key | 
|  | * manager is no longer operational and its secret value is a random value. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_disable(const dif_keymgr_t *keymgr); | 
|  |  | 
|  | /** | 
|  | * Status code bit flags. | 
|  | * | 
|  | * See also: `dif_keymgr_status_codes_t`. | 
|  | */ | 
|  | typedef enum dif_keymgr_status_code { | 
|  | /** | 
|  | * Key manager is idle. | 
|  | */ | 
|  | kDifKeymgrStatusCodeIdle = 1 << 0, | 
|  | /** | 
|  | * Software invoked an invalid operation. | 
|  | */ | 
|  | kDifKeymgrStatusCodeInvalidOperation = 1 << 1, | 
|  | /** | 
|  | * Key manager issued invalid data to KMAC interface. | 
|  | */ | 
|  | kDifKeymgrStatusCodeInvalidKmacInput = 1 << 2, | 
|  | /** | 
|  | * Software performed an invalid shadow update. | 
|  | */ | 
|  | kDifKeymgrStatusCodeInvalidKmacOutput = 1 << 3, | 
|  | /** | 
|  | * Key manager encountered invalid state | 
|  | */ | 
|  | kDifKeymgrStatusCodeInvalidState = 1 << 4, | 
|  |  | 
|  | } dif_keymgr_status_code_t; | 
|  |  | 
|  | /** | 
|  | * A bit vector of status codes. | 
|  | * | 
|  | * The following snippet can be used to check if key manager is idle: | 
|  | * | 
|  | *   `bool is_idle = (status_codes & kDifKeymgrStatusCodeIdle);` | 
|  | * | 
|  | * The following snippet can be used to check if key manager is idle and | 
|  | * error-free: | 
|  | * | 
|  | *   `bool is_idle_and_ok = (status_codes == kDifKeymgrStatusCodeIdle);` | 
|  | * | 
|  | * See also: `dif_keymgr_status_code_t`. | 
|  | */ | 
|  | typedef uint8_t dif_keymgr_status_codes_t; | 
|  |  | 
|  | /** | 
|  | * Gets the operational status of key manager. | 
|  | * | 
|  | * This function also clears OP_STATUS and ERR_CODE registers after reading | 
|  | * them. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param[out] status_codes Out-param for key manager status codes. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_get_status_codes( | 
|  | const dif_keymgr_t *keymgr, dif_keymgr_status_codes_t *status_codes); | 
|  |  | 
|  | /** | 
|  | * Gets the current state of key manager. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param[out] state Out-param for current key manager state. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr, | 
|  | dif_keymgr_state_t *state); | 
|  |  | 
|  | /** | 
|  | * Generates an identity seed. | 
|  | * | 
|  | * This function requests key manager to generate an identity seed using its | 
|  | * current secret value. Clients must first verify that the operation was | 
|  | * successful using `dif_keymgr_get_status_codes()` before reading the generated | 
|  | * identity seed using `dif_keymgr_read_output()`. | 
|  | * | 
|  | * The generated seed can be used to generate an identity using an asymmetric | 
|  | * KDF. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_generate_identity_seed(const dif_keymgr_t *keymgr); | 
|  |  | 
|  | /** | 
|  | * Destination of a versioned key generation operation. | 
|  | * | 
|  | * Key manager can make the output of a versioned key generation operation | 
|  | * available to software or sideload it directly to a peripheral device. When | 
|  | * the destination is a peripheral device, the output of the operation is not | 
|  | * visible to software and a different derivation constant is used for each | 
|  | * peripheral. | 
|  | */ | 
|  | typedef enum dif_keymgr_versioned_key_dest { | 
|  | /** | 
|  | * Store the generated versioned key in software visible registers. | 
|  | * | 
|  | * The generated versioned key can be read by calling | 
|  | * `dif_keymgr_read_output()` after verifying that the operation was | 
|  | * successful using `dif_keymgr_get_status_codes()`. | 
|  | */ | 
|  | kDifKeymgrVersionedKeyDestSw, | 
|  | /** | 
|  | * Sideload the generated versioned key to AES device. | 
|  | */ | 
|  | kDifKeymgrVersionedKeyDestAes, | 
|  | /** | 
|  | * Sideload the generated versioned key to KMAC device. | 
|  | */ | 
|  | kDifKeymgrVersionedKeyDestKmac, | 
|  | /** | 
|  | * Sideload the generated versioned key to Otbn device. | 
|  | */ | 
|  | kDifKeymgrVersionedKeyDestOtbn, | 
|  | /** | 
|  | * \internal Last key destination. | 
|  | */ | 
|  | kDifKeymgrVersionedKeyDestLast = kDifKeymgrVersionedKeyDestOtbn, | 
|  | } dif_keymgr_versioned_key_dest_t; | 
|  |  | 
|  | /** | 
|  | * Parameters for generating a versioned key. | 
|  | */ | 
|  | typedef struct dif_keymgr_versioned_key_params { | 
|  | /** | 
|  | * Destination of the generated versioned key. | 
|  | * | 
|  | * See also: `dif_keymgr_versioned_key_dest_t`. | 
|  | */ | 
|  | dif_keymgr_versioned_key_dest_t dest; | 
|  | /** | 
|  | * Salt value to use for key generation. | 
|  | */ | 
|  | uint32_t salt[8]; | 
|  | /** | 
|  | * Version value to use for key generation. | 
|  | */ | 
|  | uint32_t version; | 
|  | } dif_keymgr_versioned_key_params_t; | 
|  |  | 
|  | /** | 
|  | * Generates a versioned key. | 
|  | * | 
|  | * This function requests key manager to generate a versioned key using its | 
|  | * current secret value and the provided parameters. The generated key can be | 
|  | * sideloaded directly to a peripheral device or made visible to software using | 
|  | * `params.dest`. If the destination is software, clients must first verify that | 
|  | * the operation was successful using `dif_keymgr_get_status_codes()` before | 
|  | * reading the generated key using `dif_keymgr_read_output()`. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param params Key generation parameters. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_generate_versioned_key( | 
|  | const dif_keymgr_t *keymgr, dif_keymgr_versioned_key_params_t params); | 
|  |  | 
|  | /** | 
|  | * Starts or stops clearing of sideload keys. | 
|  | * | 
|  | * When a key is generated to be sideloaded to a hardware peripheral, key | 
|  | * manager stores it in a set of storage registers. Calling this function with | 
|  | * `state` set to `kDifKeymgrToggleEnabled` causes key manager to clear sideload | 
|  | * keys continously using random values from the entropty source. Callers must | 
|  | * disable clearing of sideload keys to resume normal sideload operation. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param state The new toggle state for sideload clear. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_sideload_clear_set_enabled(const dif_keymgr_t *keymgr, | 
|  | dif_toggle_t state); | 
|  |  | 
|  | /** | 
|  | * Checks whether clearing of sideload keys is enabled or not. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param[out] Out-param for the current toggle state of sideload clear. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_sideload_clear_get_enabled(const dif_keymgr_t *keymgr, | 
|  | dif_toggle_t *state); | 
|  |  | 
|  | /** | 
|  | * Output of a key manager operation. | 
|  | * | 
|  | * Key manager outputs are in two-shares. | 
|  | */ | 
|  | typedef struct dif_keymgr_output { | 
|  | uint32_t value[2][8]; | 
|  | } dif_keymgr_output_t; | 
|  |  | 
|  | /** | 
|  | * Reads the output of the last key manager operation. | 
|  | * | 
|  | * After starting a key manager operation, clients must verify that the | 
|  | * operation was successful using `dif_keymgr_get_status_codes()` before calling | 
|  | * this function. | 
|  | * | 
|  | * When key manager is used for versioned key generation, the output of this | 
|  | * function is valid only if the destination of the operation was | 
|  | * `kDifKeymgrVersionedKeyDestSw`. | 
|  | * | 
|  | * See also: `dif_keymgr_output_t`. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param[out] output Out-param for key manager output. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_read_output(const dif_keymgr_t *keymgr, | 
|  | dif_keymgr_output_t *output); | 
|  | /** | 
|  | * Attestation and sealing binding value. | 
|  | */ | 
|  | typedef struct dif_keymgr_binding_value { | 
|  | /** | 
|  | * Sealing binding value. | 
|  | */ | 
|  | uint32_t sealing[8]; | 
|  | /** | 
|  | * Attestation binding value. | 
|  | */ | 
|  | uint32_t attestation[8]; | 
|  | } dif_keymgr_binding_value_t; | 
|  |  | 
|  | /** | 
|  | * Reads both the attestation or the binding value set. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param[out] output Value read. | 
|  | * @return The result of the operation. | 
|  | */ | 
|  | OT_WARN_UNUSED_RESULT | 
|  | dif_result_t dif_keymgr_read_binding(const dif_keymgr_t *keymgr, | 
|  | dif_keymgr_binding_value_t *output); | 
|  |  | 
|  | typedef struct dif_keymgr_max_key_version { | 
|  | /** | 
|  | * Max creator key version. | 
|  | */ | 
|  | uint32_t creator_max_key_version; | 
|  | /** | 
|  | * Max owner intermediate key version. | 
|  | */ | 
|  | uint32_t owner_int_max_key_version; | 
|  | /** | 
|  | * Max owner key version. | 
|  | */ | 
|  | uint32_t owner_max_key_version; | 
|  | } dif_keymgr_max_key_version_t; | 
|  |  | 
|  | /** | 
|  | * Reads the max key version of each stage. | 
|  | * | 
|  | * @param keymgr A key manager handle. | 
|  | * @param version Struct with the max versions set. | 
|  | * @return dif_result_t | 
|  | */ | 
|  | dif_result_t dif_keymgr_read_max_key_version( | 
|  | const dif_keymgr_t *keymgr, dif_keymgr_max_key_version_t *versions); | 
|  | #ifdef __cplusplus | 
|  | }  // extern "C" | 
|  | #endif  // __cplusplus | 
|  |  | 
|  | #endif  // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_ |