blob: a5991fe1c3a303a0898fe33159cea19cf3d1a336 [file] [log] [blame]
// 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_