| // 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_device: "tlul", | |
| interrupt_list: [ | |
| { name: "op_done", desc: "Operation complete" }, | |
| ], | |
| alert_list: [ | |
| { name: "fault_err", | |
| desc: "Alert for key manager faults. These errors cannot be caused by software", | |
| }, | |
| { name: "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: "kmac_data", // kmac_data_req_t, kmac_data_rsp_t | |
| type: "req_rsp", | |
| name: "kmac_data", // kmac_data_o (req), kmac_data_i (rsp) | |
| act: "req", | |
| package: "keymgr_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_hw_cfg", | |
| type: "uni", | |
| name: "otp_hw_cfg", | |
| act: "rcv", | |
| package: "otp_ctrl_part_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", | |
| }, | |
| ], | |
| 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: "NumInReg", | |
| desc: "Number of Registers for SW inputs (SW binding / keyID / Salt)", | |
| type: "int", | |
| default: "4", | |
| 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: "CFGEN", | |
| 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: "CFGEN", | |
| 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 * NumInReg * 3 bits for 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_EN", | |
| 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. | |
| ''' | |
| }, | |
| ] | |
| 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: "CFGEN", | |
| 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: "NumInReg", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "31:0", | |
| name: "VAL", | |
| desc: ''' | |
| Software binding value | |
| ''', | |
| resval: "0" | |
| }, | |
| ], | |
| }, | |
| }, | |
| { multireg: { | |
| cname: "KEYMGR", | |
| name: "Salt", | |
| regwen: "CFGEN", | |
| desc: ''' | |
| Salt value used as part of output generation | |
| ''', | |
| count: "NumInReg", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "31:0", | |
| name: "VAL", | |
| desc: ''' | |
| Salt value | |
| ''', | |
| resval: "0" | |
| }, | |
| ], | |
| }, | |
| }, | |
| { multireg: { | |
| cname: "KEYMGR", | |
| name: "KEY_VERSION", | |
| regwen: "CFGEN", | |
| 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_EN", | |
| 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_EN", | |
| 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_EN", | |
| 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_EN", | |
| 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_EN", | |
| 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_EN", | |
| 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.", | |
| }, | |
| ] | |
| }, | |
| ], | |
| } |