blob: b2546a684b7c761f8e18daf7b1815092047d5c0c [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{ name: "KEYMGR",
clock_primary: "clk_i",
other_clock_list: [ "clk_edn_i" ]
reset_primary: "rst_ni",
other_reset_list: [ "rst_edn_ni" ]
bus_interfaces: [
{ protocol: "tlul", direction: "device" }
],
interrupt_list: [
{ name: "op_done", desc: "Operation complete" },
],
alert_list: [
{ name: "fatal_fault_err",
desc: "Alert for key manager faults. These errors cannot be caused by software",
},
{ name: "recov_operation_err",
desc: '''
Alert for key manager operation errors. These errors could have been caused by
software'''
}
],
// Define keymgr <-> kmac / aes / hmac struct packages
inter_signal_list: [
{ struct: "edn",
type: "req_rsp",
name: "edn",
act: "req",
package: "edn_pkg",
},
{ struct: "hw_key_req", // aes_key_req_t
type: "uni",
name: "aes_key", // aes_key_o (req)
act: "req",
package: "keymgr_pkg", // Origin package (only needs for the requester)
},
{ struct: "hw_key_req", // hmac_key_req_t
type: "uni",
name: "hmac_key", // hmac_key_o (req)
act: "req",
package: "keymgr_pkg", // Origin package (only needs for the requester)
},
{ struct: "hw_key_req", // kmac_key_req_t
type: "uni",
name: "kmac_key", // kmac_key_o (req)
act: "req",
package: "keymgr_pkg", // Origin package (only needs for the requester)
},
{ struct: "app", // kmac_pkg::app_req_t, kmac_pkg::app_rsp_t
type: "req_rsp",
name: "kmac_data", // kmac_data_o (req), kmac_data_i (rsp)
act: "req",
package: "kmac_pkg", // Origin package (only needs for the requester)
},
{ struct: "otp_keymgr_key",
type: "uni",
name: "otp_key",
act: "rcv",
package: "otp_ctrl_pkg",
},
{ struct: "otp_device_id",
type: "uni",
name: "otp_device_id",
act: "rcv",
package: "otp_ctrl_pkg",
},
{ struct: "keymgr_flash",
type: "uni",
name: "flash",
act: "rcv",
package: "flash_ctrl_pkg",
},
{ struct: "lc_tx",
type: "uni",
name: "lc_keymgr_en",
act: "rcv",
package: "lc_ctrl_pkg",
default: "lc_ctrl_pkg::On",
},
{ struct: "lc_keymgr_div",
type: "uni",
name: "lc_keymgr_div",
act: "rcv",
package: "lc_ctrl_pkg",
},
{ struct: "keymgr_data"
type: "uni"
name: "rom_digest"
act: "rcv"
package: "rom_ctrl_pkg"
},
],
param_list: [
// Random netlist constants
{ name: "RndCnstLfsrSeed",
desc: "Compile-time random bits for initial LFSR seed",
type: "keymgr_pkg::lfsr_seed_t"
randcount: "64",
randtype: "data",
}
{ name: "RndCnstLfsrPerm",
desc: "Compile-time random permutation for LFSR output",
type: "keymgr_pkg::lfsr_perm_t"
randcount: "64",
randtype: "perm",
},
{ name: "RndCnstRandPerm",
desc: "Compile-time random permutation for entropy used in share overriding",
type: "keymgr_pkg::rand_perm_t"
randcount: "32",
randtype: "perm",
}
{ name: "RndCnstRevisionSeed",
desc: "Compile-time random bits for revision seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstCreatorIdentitySeed",
desc: "Compile-time random bits for creator identity seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstOwnerIntIdentitySeed",
desc: "Compile-time random bits for owner intermediate identity seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstOwnerIdentitySeed",
desc: "Compile-time random bits for owner identity seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstSoftOutputSeed",
desc: "Compile-time random bits for software generation seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstHardOutputSeed",
desc: "Compile-time random bits for hardware generation seed",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstAesSeed",
desc: "Compile-time random bits for generation seed when aes destination selected",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstHmacSeed",
desc: "Compile-time random bits for generation seed when hmac destination selected",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstKmacSeed",
desc: "Compile-time random bits for generation seed when kmac destination selected",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "RndCnstNoneSeed",
desc: "Compile-time random bits for generation seed when no destination selected",
type: "keymgr_pkg::seed_t"
randcount: "256",
randtype: "data",
},
{ name: "NumSaltReg",
desc: "Number of Registers for SW inputs (Salt)",
type: "int",
default: "8",
local: "true"
},
{ name: "NumSwBindingReg",
desc: "Number of Registers for SW inputs (SW binding)",
type: "int",
default: "8",
local: "true"
},
{ name: "NumOutReg",
desc: "Number of Registers for SW outputs",
type: "int",
default: "8",
local: "true"
},
{ name: "NumKeyVersion",
desc: "Number of Registers for key version",
type: "int",
default: "1",
local: "true"
},
],
regwidth: "32",
registers: [
{ name: "CFG_REGWEN",
desc: "Key manager configuration enable",
swaccess: "ro", // this particular lock is meant to be fully HW managed
hwaccess: "hwo",
hwext: "true",
fields: [
{ bits: "0",
name: "EN",
resval: "1"
desc: '''
key manager configuration enable.
When key manager operation is started (see CONTROL), registers protected by this EN are no longer
modifiable until the operation completes.
TBD
This should be enhanced to support multi-bit values in the future. Should be another script change.
'''
},
]
},
{ name: "CONTROL",
desc: "Key manager operation controls",
regwen: "CFG_REGWEN",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "0",
hwaccess: "hrw",
name: "START",
desc: "Start key manager operations",
resval: "0"
enum: [
{ value: "1",
name: "Valid state",
desc: '''
To trigger a start, this value must be programmed. All other values are considered no operation start.
'''
},
]
tags: [// bit self clears, handle in directed test
"excl:CsrNonInitTests:CsrExclWrite"]
},
{ bits: "6:4",
name: "OPERATION",
desc: "Key manager operation selection. All values not enumerated below behave the same as disable",
resval: "1",
enum: [
{ value: "0",
name: "Advance",
desc: '''
Advance key manager state.
Advances key manager to the next stage.
If key manager is already at last functional state, the advance operation is equivalent to the
disable operation.
'''
},
{ value: "1",
name: "Generate ID",
desc: '''
Generates an identity seed from the current state.
'''
},
{ value: "2",
name: "Generate SW Output",
desc: '''
Generates a key manager output that is visible to software from the current state.
'''
},
{ value: "3",
name: "Generate HW Output",
desc: '''
Generates a key manager output that is visible only to hardware crypto blocks.
'''
},
{ value: "4",
name: "Disable",
desc: '''
Disables key manager operation and moves it to the disabled state.
Note the disabled state is terminal and cannot be recovered without a reset.
'''
},
]
},
{ bits: "13:12",
name: "DEST_SEL",
desc: '''
When the OPERATION field is programmed to generate output, this field selects
the appropriate crypto cipher target.
This field should be programmed for both hw / sw generation, as this helps diverisifies the output.
''',
resval: "0"
enum: [
{ value: "0",
name: "None",
desc: '''
No target selected
'''
},
{ value: "1",
name: "AES",
desc: '''
AES selected
'''
},
{ value: "2",
name: "HMAC",
desc: '''
HMAC selected
'''
},
{ value: "3",
name: "KMAC",
desc: '''
KMAC selected
'''
},
]
},
],
},
{ name: "SIDELOAD_CLEAR",
desc: "Clear all sideload keys",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "0",
name: "VAL",
resval: "0"
desc: '''
When 1, the sideload keys are continuously cleared with entropy.
When 0, the sideload keys are left as is.
'''
},
]
},
{ name: "RESEED_INTERVAL",
desc: "reseed interval for key manager entropy reseed",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "15:0",
name: "VAL",
resval: "0x100"
desc: '''
Number of key manager cycles before the entropy is reseeded
'''
},
]
},
// The following can potentially be replaced by a RAM if it gets too large
// Currently there are 32b * NumSaltReg bits for salt inputs
// 32b * NumSwBindingReg bits for software binding inputs
// 32b * NumOutReg * 2 (if key shares desired) for outputs
// 32b * NumOutReg * NumCryptos * 2 (if key shares desired) for hidden key bus
// This totals to over 2kb of storage
{ name: "SW_BINDING_REGWEN",
desc: "Register write enable for SOFTWARE_BINDING",
swaccess: "rw0c",
hwaccess: "hrw",
hwext: "true",
hwqe: "true",
fields: [
{ bits: "0",
name: "EN",
resval: "1"
desc: '''
Software binding register write enable.
This is locked by software and unlocked by hardware upon a successful advance call.
Software binding resets to 1, and its value cannot be altered by software until advancement to Init state.
'''
},
]
tags: [// when it's set, it can't be modified until the next advance operation completes
"excl:CsrNonInitTests:CsrExclWrite"]
},
{ multireg: {
cname: "KEYMGR",
name: "SW_BINDING",
regwen: "SW_BINDING_REGWEN",
desc: '''
Software binding input to key manager.
This register is lockable and shared between key manager stages.
This binding value is not considered secret, however its integrity is very important.
The software binding is locked by software and unlocked by hardware upon a successful advance operation.
''',
count: "NumSwBindingReg",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "31:0",
name: "VAL",
desc: '''
Software binding value
''',
resval: "0"
},
],
},
},
{ multireg: {
cname: "KEYMGR",
name: "Salt",
regwen: "CFG_REGWEN",
desc: '''
Salt value used as part of output generation
''',
count: "NumSaltReg",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "31:0",
name: "VAL",
desc: '''
Salt value
''',
resval: "0"
},
],
},
},
{ multireg: {
cname: "KEYMGR",
name: "KEY_VERSION",
regwen: "CFG_REGWEN",
desc: '''
Version used as part of output generation
''',
count: "NumKeyVersion",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "31:0",
name: "VAL",
desc: '''
Salt value
''',
resval: "0"
},
],
},
},
// since there is not a good way to define a separate enable register per multireg
// the following version registers are manually separated
// further, it should be possible to reduce the number of max_versions held
// as long as clearly specify the boot sequence relative to when keys are generated.
// should check with the security team.
//
// The following storage is also huge, should consider switching to RAMs after examining
// the security implications
{ name: "MAX_CREATOR_KEY_VER_REGWEN",
desc: "Register write enable for MAX_CREATOR_KEY_VERSION",
swaccess: "rw0c",
hwaccess: "none",
fields: [
{ bits: "0",
name: "EN",
resval: "1"
desc: '''
MAX_CREATOR_KEY_VERSION configure enable.
All values except for 2 are interpreted as configuration disable.
'''
},
]
},
{ name: "MAX_CREATOR_KEY_VER",
desc: "Max creator key version",
swaccess: "rw",
hwaccess: "hro",
regwen: "MAX_CREATOR_KEY_VER_REGWEN",
fields: [
{ bits: "31:0",
name: "VAL",
resval: "0x0"
desc: '''
Max key version.
Any key version up to the value specificed in this register is valid.
'''
},
]
},
{ name: "MAX_OWNER_INT_KEY_VER_REGWEN",
desc: "Register write enable for MAX_OWNER_INT_KEY_VERSION",
swaccess: "rw0c",
hwaccess: "none",
fields: [
{ bits: "0",
name: "EN",
resval: "1"
desc: '''
MAX_OWNER_INTERMEDIATE_KEY configure enable.
All values except for 2 are interpreted as configuration disable.
'''
},
]
},
{ name: "MAX_OWNER_INT_KEY_VER",
desc: "Max owner intermediate key version",
swaccess: "rw",
hwaccess: "hro",
regwen: "MAX_OWNER_INT_KEY_VER_REGWEN",
fields: [
{ bits: "31:0",
name: "VAL",
resval: "1"
desc: '''
Max key version.
Any key version up to the value specificed in this register is valid.
'''
},
]
},
{ name: "MAX_OWNER_KEY_VER_REGWEN",
desc: "Register write enable for MAX_OWNER_KEY_VERSION",
swaccess: "rw0c",
hwaccess: "none",
fields: [
{ bits: "0",
name: "EN",
resval: "1"
desc: '''
MAX_OWNER_KEY configure enable.
All values except for 2 are interpreted as configuration disable.
'''
},
]
},
{ name: "MAX_OWNER_KEY_VER",
desc: "Max owner key version",
swaccess: "rw",
hwaccess: "hro",
regwen: "MAX_OWNER_KEY_VER_REGWEN",
fields: [
{ bits: "31:0",
name: "VAL",
resval: "0x0"
desc: '''
Max key version.
Any key version up to the value specificed in this register is valid.
'''
},
]
},
{ multireg: {
cname: "KEYMGR",
name: "SW_SHARE0_OUTPUT",
desc: '''
Key manager software output.
When a software output operation is selected, the results of the operation are placed
here.
''',
count: "NumOutReg",
swaccess: "rc",
hwaccess: "hwo",
fields: [
{ bits: "31:0",
name: "VAL",
desc: '''
Software output value
''',
resval: "0"
},
],
},
},
{ multireg: {
cname: "KEYMGR",
name: "SW_SHARE1_OUTPUT",
desc: '''
Key manager software output.
When a software output operation is selected, the results of the operation are placed
here.
''',
count: "NumOutReg",
swaccess: "rc",
hwaccess: "hwo",
fields: [
{ bits: "31:0",
name: "VAL",
desc: '''
Software output value
''',
resval: "0"
},
],
},
},
{ name: "WORKING_STATE",
desc: '''
Key manager working state.
This is a readout of the current key manager working state
''',
swaccess: "ro",
hwaccess: "hwo",
fields: [
{ bits: "2:0",
name: "STATE",
resval: "0x0"
desc: "Key manager control state",
enum: [
{ value: "0",
name: "Reset",
desc: '''
Key manager control is still in reset. Please wait for initialization complete
before issuing operations
'''
},
{ value: "1",
name: "Init",
desc: '''
Key manager control has finished initialization and will now accept
software commands.
'''
},
{ value: "2",
name: "Creator Root Key",
desc: '''
Key manager control currently contains the creator root key.
'''
},
{ value: "3",
name: "Owner Intermediate Key",
desc: '''
Key manager control currently contains the owner intermediate key.
'''
},
{ value: "4",
name: "Owner Key",
desc: '''
Key manager control currently contains the owner key.
'''
},
{ value: "5",
name: "Disabled",
desc: '''
Key manager currently disabled. Please reset the key manager.
Sideload keys are still valid.
'''
},
{ value: "6",
name: "Invalid",
desc: '''
Key manager currently invalid. Please reset the key manager.
Sideload keys are no longer valid.
'''
},
]
}
]
},
{ name: "OP_STATUS",
desc: '''
Key manager status.
Hardware sets the status based on software initiated operations.
This register must be explicitly cleared by software.
Software clears by writing back whatever it reads.
''',
swaccess: "rw1c",
hwaccess: "hwo",
fields: [
{ bits: "1:0",
name: "STATUS",
resval: "0x0"
desc: "Operation status.",
enum: [
{ value: "0",
name: "Idle",
desc: '''
Key manager is idle
'''
},
{ value: "1",
name: "WIP",
desc: '''
Work in progress.
A key manager operation has been started and is ongoing
'''
},
{ value: "2",
name: "DONE_SUCCESS",
desc: '''
Operation finished without errors
'''
},
{ value: "3",
name: "DONE_ERROR",
desc: '''
Operation finished with errors, please see ERR_CODE register.
'''
},
]
},
]
},
{ name: "ERR_CODE",
desc: '''
Key manager error code.
This register must be explicitly cleared by software.
Software clears by writing back whatever it reads.
''',
swaccess: "rw1c",
hwaccess: "hrw",
fields: [
{ bits: "0",
name: "INVALID_OP",
resval: "0x0"
desc: "Invalid operation issued to key manager",
},
{ bits: "1",
name: "INVALID_CMD",
resval: "0x0"
desc: "Invalid command issued from key manager to kmac interface",
},
{ bits: "2",
name: "INVALID_KMAC_INPUT",
resval: "0x0"
desc: "Invalid data issued to kmac interface",
},
{ bits: "3",
name: "INVALID_KMAC_DATA",
resval: "0x0"
desc: "Invalid data returned from kmac interface.",
},
]
},
],
}