Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Key manager top level |
| 6 | // |
| 7 | |
| 8 | `include "prim_assert.sv" |
| 9 | |
Timothy Chen | 5d06aac | 2021-08-09 17:08:24 -0700 | [diff] [blame] | 10 | module keymgr_ctrl import keymgr_pkg::*; #( |
| 11 | parameter bit KmacEnMasking = 1'b1 |
| 12 | ) ( |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 13 | input clk_i, |
| 14 | input rst_ni, |
| 15 | |
| 16 | // lifecycle enforcement |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 17 | input en_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 18 | |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 19 | // faults that can occur outside of operations |
| 20 | input regfile_intg_err_i, |
Timothy Chen | 4fb25fc | 2021-08-19 18:15:08 -0700 | [diff] [blame] | 21 | input shadowed_update_err_i, |
| 22 | input shadowed_storage_err_i, |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 23 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 24 | // Software interface |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 25 | input op_start_i, |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 26 | input keymgr_ops_e op_i, |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 27 | input [CdiWidth-1:0] op_cdi_sel_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 28 | output logic op_done_o, |
| 29 | output keymgr_op_status_e status_o, |
| 30 | output logic [ErrLastPos-1:0] error_o, |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 31 | output logic [FaultLastPos-1:0] fault_o, |
Timothy Chen | 8cf1a3a | 2020-12-08 19:05:29 -0800 | [diff] [blame] | 32 | output logic data_en_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 33 | output logic data_valid_o, |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 34 | output logic wipe_key_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 35 | output keymgr_working_state_e working_state_o, |
Timothy Chen | 12ca862 | 2020-12-08 12:29:44 -0800 | [diff] [blame] | 36 | output logic sw_binding_unlock_o, |
Timothy Chen | 0a12094 | 2020-12-14 17:20:51 -0800 | [diff] [blame] | 37 | output logic init_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 38 | |
| 39 | // Data input |
Timothy Chen | 65e1667 | 2020-12-05 09:17:14 -0800 | [diff] [blame] | 40 | input otp_ctrl_pkg::otp_keymgr_key_t root_key_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 41 | output keymgr_gen_out_e hw_sel_o, |
| 42 | output keymgr_stage_e stage_sel_o, |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 43 | output logic [CdiWidth-1:0] cdi_sel_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 44 | |
| 45 | // KMAC ctrl interface |
| 46 | output logic adv_en_o, |
| 47 | output logic id_en_o, |
| 48 | output logic gen_en_o, |
Timothy Chen | 8cf1a3a | 2020-12-08 19:05:29 -0800 | [diff] [blame] | 49 | output hw_key_req_t key_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 50 | input kmac_done_i, |
| 51 | input kmac_input_invalid_i, // asserted when selected data fails criteria check |
| 52 | input kmac_fsm_err_i, // asserted when kmac fsm reaches unexpected state |
Timothy Chen | eaa3f2b | 2020-10-27 17:10:15 -0700 | [diff] [blame] | 53 | input kmac_op_err_i, // asserted when kmac itself reports an error |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 54 | input kmac_cmd_err_i, // asserted when more than one command given to kmac |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 55 | input [Shares-1:0][KeyWidth-1:0] kmac_data_i, |
| 56 | |
| 57 | // prng control interface |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 58 | input [Shares-1:0][RandWidth-1:0] entropy_i, |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 59 | input prng_reseed_ack_i, |
| 60 | output logic prng_reseed_req_o, |
| 61 | output logic prng_en_o |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 62 | ); |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 63 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 64 | localparam int EntropyWidth = LfsrWidth / 2; |
| 65 | localparam int EntropyRounds = KeyWidth / EntropyWidth; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 66 | localparam int EntropyRndWidth = prim_util_pkg::vbits(EntropyRounds); |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 67 | localparam int CntWidth = EntropyRounds > CDIs ? EntropyRndWidth : CdiWidth; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 68 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 69 | // Enumeration for working state |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 70 | // Encoding generated with: |
| 71 | // $ ./util/design/sparse-fsm-encode.py -d 5 -m 11 -n 10 \ |
| 72 | // -s 4101887575 --language=sv |
| 73 | // |
| 74 | // Hamming distance histogram: |
| 75 | // |
| 76 | // 0: -- |
| 77 | // 1: -- |
| 78 | // 2: -- |
| 79 | // 3: -- |
| 80 | // 4: -- |
| 81 | // 5: |||||||||||||||||||| (54.55%) |
| 82 | // 6: |||||||||||||||| (45.45%) |
| 83 | // 7: -- |
| 84 | // 8: -- |
| 85 | // 9: -- |
| 86 | // 10: -- |
| 87 | // |
| 88 | // Minimum Hamming distance: 5 |
| 89 | // Maximum Hamming distance: 6 |
| 90 | // Minimum Hamming weight: 2 |
| 91 | // Maximum Hamming weight: 8 |
| 92 | // |
| 93 | localparam int StateWidth = 10; |
| 94 | typedef enum logic [StateWidth-1:0] { |
| 95 | StCtrlReset = 10'b1101100001, |
| 96 | StCtrlEntropyReseed = 10'b1110010010, |
| 97 | StCtrlRandom = 10'b0011110100, |
| 98 | StCtrlRootKey = 10'b0110101111, |
| 99 | StCtrlInit = 10'b0100000100, |
| 100 | StCtrlCreatorRootKey = 10'b1000011101, |
| 101 | StCtrlOwnerIntKey = 10'b0001001010, |
| 102 | StCtrlOwnerKey = 10'b1101111110, |
| 103 | StCtrlDisabled = 10'b1010101000, |
| 104 | StCtrlWipe = 10'b0000110011, |
| 105 | StCtrlInvalid = 10'b1011000111 |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 106 | } keymgr_ctrl_state_e; |
| 107 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 108 | // Enumeration for operation handling |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 109 | typedef enum logic [1:0] { |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 110 | StIdle, |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 111 | StAdv, |
| 112 | StAdvAck, |
| 113 | StWait |
| 114 | } keymgr_op_state_e; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 115 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 116 | keymgr_ctrl_state_e state_q, state_d; |
| 117 | keymgr_op_state_e op_state_q, op_state_d; |
| 118 | |
| 119 | // There are two versions of the key state, one for sealing one for attestation |
| 120 | // Among each version, there are multiple shares |
| 121 | // Each share is a fixed multiple of the entropy width |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 122 | logic [CDIs-1:0][Shares-1:0][EntropyRounds-1:0][EntropyWidth-1:0] key_state_q, key_state_d; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 123 | logic [CntWidth-1:0] cnt; |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 124 | logic [CdiWidth-1:0] cdi_cnt; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 125 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 126 | // error conditions |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 127 | logic invalid_kmac_out; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 128 | logic invalid_op; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 129 | logic cnt_err; |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 130 | // states fall out of sparsely encoded range |
| 131 | logic state_intg_err_q, state_intg_err_d; |
| 132 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 133 | /////////////////////////// |
| 134 | // General operation decode |
| 135 | /////////////////////////// |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 136 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 137 | logic adv_op, dis_op, gen_id_op, gen_sw_op, gen_hw_op, gen_op; |
| 138 | assign adv_op = (op_i == OpAdvance); |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 139 | assign gen_id_op = (op_i == OpGenId); |
| 140 | assign gen_sw_op = (op_i == OpGenSwOut); |
| 141 | assign gen_hw_op = (op_i == OpGenHwOut); |
Timothy Chen | d391e88 | 2021-09-08 12:27:13 -0700 | [diff] [blame] | 142 | assign dis_op = ~(op_i inside {OpAdvance, OpGenId, OpGenSwOut, OpGenHwOut}); |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 143 | assign gen_op = (gen_id_op | gen_sw_op | gen_hw_op); |
| 144 | |
| 145 | /////////////////////////// |
| 146 | // interaction between software and main fsm |
| 147 | /////////////////////////// |
| 148 | // disable is treated like an advanced call |
| 149 | logic advance_sel; |
| 150 | logic disable_sel; |
| 151 | logic gen_out_hw_sel; |
| 152 | |
| 153 | assign advance_sel = op_start_i & adv_op & en_i; |
| 154 | assign gen_out_hw_sel = op_start_i & gen_hw_op & en_i; |
| 155 | |
| 156 | // disable is selected whenever a normal operation is not set |
| 157 | assign disable_sel = (op_start_i & dis_op) | !en_i; |
| 158 | |
| 159 | |
| 160 | /////////////////////////// |
| 161 | // interaction between main control fsm and operation fsm |
| 162 | /////////////////////////// |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 163 | |
| 164 | // req/ack interface with op handling fsm |
| 165 | logic op_req; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 166 | logic op_ack; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 167 | logic op_update; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 168 | logic op_busy; |
| 169 | logic disabled; |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 170 | logic invalid; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 171 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 172 | logic adv_req, dis_req, id_req, gen_req; |
| 173 | assign adv_req = op_req & adv_op; |
| 174 | assign dis_req = op_req & dis_op; |
| 175 | assign id_req = op_req & gen_id_op; |
| 176 | assign gen_req = op_req & (gen_sw_op | gen_hw_op); |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 177 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 178 | /////////////////////////// |
| 179 | // interaction between operation fsm and software |
| 180 | /////////////////////////// |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 181 | // categories of keymgr errors |
| 182 | logic [SyncErrLastIdx-1:0] sync_err; |
| 183 | logic [AsyncErrLastIdx-1:0] async_err; |
| 184 | logic [SyncFaultLastIdx-1:0] sync_fault; |
| 185 | logic [AsyncFaultLastIdx-1:0] async_fault; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 186 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 187 | logic op_err; |
| 188 | logic op_fault_err; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 189 | |
Timothy Chen | 12ca862 | 2020-12-08 12:29:44 -0800 | [diff] [blame] | 190 | // unlock sw binding configuration whenever an advance call is made without errors |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 191 | assign sw_binding_unlock_o = adv_req & op_ack & ~(op_err | op_fault_err); |
Timothy Chen | 12ca862 | 2020-12-08 12:29:44 -0800 | [diff] [blame] | 192 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 193 | // error definition |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 194 | // check incoming kmac data validity |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 195 | // Only check during the periods when there is actual kmac output |
| 196 | assign invalid_kmac_out = (op_update | op_ack) & |
| 197 | (~valid_data_chk(kmac_data_i[0]) | |
| 198 | (~valid_data_chk(kmac_data_i[1]) & KmacEnMasking)); |
Timothy Chen | 754a527 | 2021-01-06 10:41:08 -0800 | [diff] [blame] | 199 | |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 200 | assign op_err = sync_err[SyncErrInvalidOp] | |
| 201 | sync_err[SyncErrInvalidIn]; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 202 | |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 203 | assign op_fault_err = |sync_fault | |
| 204 | |async_fault; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 205 | |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 206 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 207 | /////////////////////////// |
| 208 | // key update controls |
| 209 | /////////////////////////// |
| 210 | |
| 211 | // update select can come from both main and operation fsm's |
| 212 | keymgr_key_update_e update_sel, op_update_sel; |
| 213 | |
| 214 | // req from main control fsm to key update controls |
| 215 | logic wipe_req; |
| 216 | logic random_req; |
| 217 | logic random_ack; |
| 218 | |
| 219 | // wipe and initialize take precedence |
| 220 | assign update_sel = wipe_req ? KeyUpdateWipe : |
| 221 | random_req ? KeyUpdateRandom : |
| 222 | init_o ? KeyUpdateRoot : op_update_sel; |
| 223 | |
| 224 | /////////////////////////// |
| 225 | // interaction between main fsm and prng |
| 226 | /////////////////////////// |
| 227 | |
| 228 | logic prng_en; |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 229 | assign prng_en_o = prng_en | disabled | invalid | wipe_req; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 230 | |
| 231 | ////////////////////////// |
| 232 | // Main Control FSM |
| 233 | ////////////////////////// |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 234 | |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 235 | logic [StateWidth-1:0] state_raw_q; |
| 236 | assign state_q = keymgr_ctrl_state_e'(state_raw_q); |
| 237 | prim_flop #( |
| 238 | .Width(StateWidth), |
| 239 | .ResetValue(StateWidth'(StCtrlReset)) |
| 240 | ) u_state_regs ( |
| 241 | .clk_i, |
| 242 | .rst_ni, |
| 243 | .d_i ( state_d ), |
| 244 | .q_o ( state_raw_q ) |
| 245 | ); |
| 246 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 247 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 248 | if (!rst_ni) begin |
| 249 | state_intg_err_q <= '0; |
| 250 | end else begin |
| 251 | state_intg_err_q <= state_intg_err_d; |
| 252 | end |
| 253 | end |
| 254 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 255 | // prevents unknowns from reaching the outside world. |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 256 | // - whatever operation causes the input data select to be disabled should not expose the key |
| 257 | // state. |
| 258 | // - when there are no operations, the key state also should be exposed. |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 259 | assign key_o.valid = op_req; |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 260 | assign cdi_sel_o = advance_sel ? cdi_cnt : op_cdi_sel_i; |
Timothy Chen | 70151fe | 2021-07-08 12:59:21 -0700 | [diff] [blame] | 261 | |
| 262 | for (genvar i = 0; i < Shares; i++) begin : gen_key_out_assign |
| 263 | assign key_o.key[i] = stage_sel_o == Disable ? |
| 264 | {EntropyRounds{entropy_i[i]}} : |
Timothy Chen | f433eea | 2021-07-21 10:53:46 -0700 | [diff] [blame] | 265 | key_state_q[cdi_sel_o][i]; |
Timothy Chen | 70151fe | 2021-07-08 12:59:21 -0700 | [diff] [blame] | 266 | end |
| 267 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 268 | |
| 269 | // key state is intentionally not reset |
| 270 | always_ff @(posedge clk_i) begin |
| 271 | key_state_q <= key_state_d; |
| 272 | end |
| 273 | |
Timothy Chen | 65e1667 | 2020-12-05 09:17:14 -0800 | [diff] [blame] | 274 | // root key valid sync |
| 275 | logic root_key_valid_q; |
| 276 | |
| 277 | prim_flop_2sync # ( |
| 278 | .Width(1) |
| 279 | ) u_key_valid_sync ( |
| 280 | .clk_i, |
| 281 | .rst_ni, |
| 282 | .d_i(root_key_i.valid), |
| 283 | .q_o(root_key_valid_q) |
| 284 | ); |
| 285 | |
Timothy Chen | f433eea | 2021-07-21 10:53:46 -0700 | [diff] [blame] | 286 | // Do not let the count toggle unless an advance operation is |
| 287 | // selected |
| 288 | assign cdi_cnt = op_req ? cnt[CdiWidth-1:0] : '0; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 289 | |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 290 | always_comb begin |
| 291 | key_state_d = key_state_q; |
| 292 | data_valid_o = 1'b0; |
| 293 | wipe_key_o = 1'b0; |
| 294 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 295 | // if a wipe request arrives, immediately destroy the |
| 296 | // keys regardless of current state |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 297 | unique case (update_sel) |
| 298 | KeyUpdateRandom: begin |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 299 | for (int i = 0; i < CDIs; i++) begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 300 | for (int j = 0; j < Shares; j++) begin |
| 301 | key_state_d[i][j][cnt[EntropyRndWidth-1:0]] = entropy_i[j]; |
| 302 | end |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 303 | end |
| 304 | end |
| 305 | |
| 306 | KeyUpdateRoot: begin |
| 307 | if (root_key_valid_q) begin |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 308 | for (int i = 0; i < CDIs; i++) begin |
Timothy Chen | 5d06aac | 2021-08-09 17:08:24 -0700 | [diff] [blame] | 309 | if (KmacEnMasking) begin : gen_two_share_key |
| 310 | key_state_d[i][0] = root_key_i.key_share0; |
| 311 | key_state_d[i][1] = root_key_i.key_share1; |
| 312 | end else begin : gen_one_share_key |
| 313 | key_state_d[i][0] = root_key_i.key_share0 ^ root_key_i.key_share1; |
| 314 | key_state_d[i][1] = '0; |
| 315 | end |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 316 | end |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 317 | end |
| 318 | end |
| 319 | |
| 320 | KeyUpdateKmac: begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 321 | data_valid_o = gen_op; |
| 322 | key_state_d[cdi_sel_o] = (adv_op || dis_op) ? kmac_data_i : key_state_q[cdi_sel_o]; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 323 | end |
| 324 | |
| 325 | KeyUpdateWipe: begin |
| 326 | wipe_key_o = 1'b1; |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 327 | for (int i = 0; i < CDIs; i++) begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 328 | for (int j = 0; j < Shares; j++) begin |
| 329 | key_state_d[i][j] = {EntropyRounds{entropy_i[j]}}; |
| 330 | end |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 331 | end |
| 332 | end |
| 333 | |
| 334 | default:; |
| 335 | endcase // unique case (update_sel) |
| 336 | end |
| 337 | |
Timothy Chen | df2c0a7 | 2021-09-16 16:10:12 -0700 | [diff] [blame] | 338 | prim_count #( |
Timothy Chen | eb7bf61 | 2021-08-03 16:17:09 -0700 | [diff] [blame] | 339 | .Width(CntWidth), |
Timothy Chen | df2c0a7 | 2021-09-16 16:10:12 -0700 | [diff] [blame] | 340 | .CntStyle(prim_count_pkg::DupCnt) |
Timothy Chen | eb7bf61 | 2021-08-03 16:17:09 -0700 | [diff] [blame] | 341 | ) u_cnt ( |
| 342 | .clk_i, |
| 343 | .rst_ni, |
| 344 | .clr_i(op_ack | random_ack), |
| 345 | .set_i('0), |
| 346 | .set_cnt_i('0), |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 347 | .en_i(op_update | random_req), |
Timothy Chen | eb7bf61 | 2021-08-03 16:17:09 -0700 | [diff] [blame] | 348 | .cnt_o(cnt), |
| 349 | .err_o(cnt_err) |
| 350 | ); |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 351 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 352 | // TODO: Create a no select option, do not leave this as binary |
| 353 | assign hw_sel_o = gen_out_hw_sel ? HwKey : SwKey; |
| 354 | |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 355 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 356 | // when in a state that accepts commands, look at op_ack for completion |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 357 | // when in a state that does not accept commands, wait for other triggers. |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 358 | assign op_done_o = op_req ? op_ack : |
| 359 | (init_o | invalid_op); |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 360 | |
| 361 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 362 | // There are 3 possibilities |
| 363 | // advance to next state (software command) |
| 364 | // advance to disabled state (software command) |
| 365 | // advance to invalid state (detected fault) |
| 366 | logic adv_state; |
| 367 | logic dis_state; |
| 368 | logic inv_state; |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 369 | assign adv_state = op_ack & adv_req & ~op_err; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 370 | assign dis_state = op_ack & dis_req; |
Timothy Chen | d02fba7 | 2021-09-01 22:49:21 -0700 | [diff] [blame] | 371 | assign inv_state = op_ack & op_fault_err; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 372 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 373 | always_comb begin |
| 374 | // persistent data |
| 375 | state_d = state_q; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 376 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 377 | // request to op handling |
| 378 | op_req = 1'b0; |
| 379 | random_req = 1'b0; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 380 | random_ack = 1'b0; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 381 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 382 | // request to key updates |
| 383 | wipe_req = 1'b0; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 384 | |
| 385 | // invalid operation issued |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 386 | invalid_op = 1'b0; |
| 387 | |
| 388 | // data update and select signals |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 389 | stage_sel_o = Disable; |
| 390 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 391 | // indication that state is disabled |
| 392 | disabled = 1'b0; |
| 393 | |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 394 | // indication that state is invalid |
| 395 | invalid = 1'b0; |
| 396 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 397 | // enable prng toggling |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 398 | prng_reseed_req_o = 1'b0; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 399 | prng_en = 1'b0; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 400 | |
Timothy Chen | 0a12094 | 2020-12-14 17:20:51 -0800 | [diff] [blame] | 401 | // initialization complete |
| 402 | init_o = 1'b0; |
| 403 | |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 404 | // if state is ever faulted, hold on to this indication |
| 405 | // until reset. |
| 406 | state_intg_err_d = state_intg_err_q; |
| 407 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 408 | unique case (state_q) |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 409 | // Only advance can be called from reset state |
| 410 | StCtrlReset: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 411 | // in reset state, don't enable entropy yet, since there are no users. |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 412 | prng_en = 1'b0; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 413 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 414 | // always use random data for advance, since out of reset state |
| 415 | // the key state will be randomized. |
| 416 | stage_sel_o = Disable; |
| 417 | |
| 418 | // key state is updated when it is an advance call |
| 419 | // all other operations are invalid, including disable |
| 420 | if (advance_sel) begin |
| 421 | state_d = StCtrlEntropyReseed; |
| 422 | end else if (op_start_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 423 | invalid_op = 1'b1; |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 424 | end |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 425 | end |
| 426 | |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 427 | // reseed entropy |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 428 | StCtrlEntropyReseed: begin |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 429 | prng_reseed_req_o = 1'b1; |
Timothy Chen | 84b7d1b | 2021-08-12 16:42:45 -0700 | [diff] [blame] | 430 | |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 431 | if (prng_reseed_ack_i) begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 432 | state_d = StCtrlRandom; |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 433 | end |
| 434 | end |
| 435 | |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 436 | // This state does not accept any command. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 437 | StCtrlRandom: begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 438 | prng_en = 1'b1; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 439 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 440 | if (cnt < EntropyRounds-1) begin |
| 441 | random_req = 1'b1; |
| 442 | end |
| 443 | // when mask population is complete, xor the root_key into the zero share |
| 444 | // if in the future the root key is updated to 2 shares, it will direclty overwrite |
| 445 | // the values here |
| 446 | else begin |
| 447 | random_ack = 1'b1; |
| 448 | state_d = StCtrlRootKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 449 | end |
| 450 | end |
| 451 | |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 452 | // load the root key. |
| 453 | StCtrlRootKey: begin |
Timothy Chen | d02fba7 | 2021-09-01 22:49:21 -0700 | [diff] [blame] | 454 | // we cannot directly use inv_state here for 2 reasons |
| 455 | // - inv_state is sync'd to the completion of a real kmac operation, |
| 456 | // which is not the case here. |
| 457 | // - using inv_state would cause a combo loop between init_o and inv_state. |
| 458 | init_o = en_i & ~|async_fault; |
| 459 | state_d = !init_o ? StCtrlWipe : StCtrlInit; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 460 | end |
| 461 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 462 | // Beginning from the Init state, operations are accepted. |
| 463 | // Only valid operation is advance state. If invalid command received, |
| 464 | // random data is selected for operation and no persistent state is changed. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 465 | StCtrlInit: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 466 | op_req = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 467 | |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 468 | // when advancing select creator data, otherwise use random input |
| 469 | stage_sel_o = advance_sel ? Creator : Disable; |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 470 | invalid_op = op_start_i & ~(advance_sel | disable_sel); |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 471 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 472 | if (!en_i || inv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 473 | state_d = StCtrlWipe; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 474 | end else if (dis_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 475 | state_d = StCtrlDisabled; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 476 | end else if (adv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 477 | state_d = StCtrlCreatorRootKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 478 | end |
| 479 | end |
| 480 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 481 | // all commands are valid during this stage |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 482 | StCtrlCreatorRootKey: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 483 | op_req = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 484 | |
| 485 | // when generating, select creator data input |
| 486 | // when advancing, select owner intermediate key as target |
| 487 | // when disabling, select random data input |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 488 | stage_sel_o = disable_sel ? Disable : |
| 489 | advance_sel ? OwnerInt : Creator; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 490 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 491 | if (!en_i || inv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 492 | state_d = StCtrlWipe; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 493 | end else if (dis_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 494 | state_d = StCtrlDisabled; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 495 | end else if (adv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 496 | state_d = StCtrlOwnerIntKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 497 | end |
| 498 | end |
| 499 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 500 | // all commands are valid during this stage |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 501 | StCtrlOwnerIntKey: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 502 | op_req = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 503 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 504 | // when generating, select owner intermediate data input |
| 505 | // when advancing, select owner as target |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 506 | // when disabling, select random data input |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 507 | stage_sel_o = disable_sel ? Disable : |
| 508 | advance_sel ? Owner : OwnerInt; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 509 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 510 | if (!en_i || inv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 511 | state_d = StCtrlWipe; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 512 | end else if (dis_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 513 | state_d = StCtrlDisabled; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 514 | end else if (adv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 515 | state_d = StCtrlOwnerKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 516 | end |
| 517 | end |
| 518 | |
| 519 | // all commands are valid during this stage |
| 520 | // however advance goes directly to disabled state |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 521 | StCtrlOwnerKey: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 522 | op_req = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 523 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 524 | // when generating, select owner data input |
| 525 | // when advancing, select disable as target |
| 526 | // when disabling, select random data input |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 527 | stage_sel_o = disable_sel | advance_sel ? Disable : Owner; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 528 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 529 | if (!en_i || inv_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 530 | state_d = StCtrlWipe; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 531 | end else if (adv_state || dis_state) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 532 | state_d = StCtrlDisabled; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 533 | end |
| 534 | end |
| 535 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 536 | // The wipe state immediately clears out the key state, but waits for any ongoing |
| 537 | // transaction to finish before going to disabled state. |
| 538 | // Unlike the random state, this is an immedaite shutdown request, so all parts of the |
| 539 | // key are wiped. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 540 | StCtrlWipe: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 541 | wipe_req = 1'b1; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 542 | // if there was already an operation ongoing, maintain the request until completion |
| 543 | op_req = op_busy; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 544 | invalid_op = op_start_i; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 545 | |
| 546 | // If the enable is dropped during the middle of a transaction, we clear and wait for that |
| 547 | // transaction to gracefully complete (if it can). |
| 548 | // There are two scenarios: |
| 549 | // 1. the operation completed right when we started wiping, in which case the done would |
| 550 | // clear the start. |
| 551 | // 2. the operation completed before we started wiping, or there was never an operation to |
| 552 | // begin with (op_start_i == 0), in this case, don't wait and immediately transition |
| 553 | if (!op_start_i) begin |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 554 | state_d = StCtrlInvalid; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 555 | end |
| 556 | end |
| 557 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 558 | // StCtrlDisabled and StCtrlInvalid are almost functionally equivalent |
| 559 | // The only difference is that Disabled is entered through software invocation, |
| 560 | // while Invalid is entered through life cycle disable or operational fault. |
| 561 | // |
| 562 | // Both states continue to kick off random transactions |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 563 | // All transactions are treated as invalid despite completing |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 564 | StCtrlDisabled: begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 565 | op_req = op_start_i; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 566 | disabled = 1'b1; |
| 567 | |
| 568 | if (!en_i || inv_state) begin |
| 569 | state_d = StCtrlWipe; |
| 570 | end |
| 571 | end |
| 572 | |
| 573 | StCtrlInvalid: begin |
| 574 | op_req = op_start_i; |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 575 | invalid = 1'b1; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 576 | end |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 577 | |
| 578 | // latch the fault indication and start to wipe the key manager |
| 579 | default: begin |
| 580 | state_intg_err_d = 1'b1; |
| 581 | state_d = StCtrlWipe; |
| 582 | end |
| 583 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 584 | endcase // unique case (state_q) |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 585 | end // always_comb |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 586 | |
| 587 | // Current working state provided for software read |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 588 | // Certain states are collapsed for simplicity |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 589 | keymgr_working_state_e last_working_st; |
| 590 | logic state_update; |
| 591 | |
| 592 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 593 | if (!rst_ni) begin |
| 594 | last_working_st <= StReset; |
| 595 | end else if (state_update) begin |
| 596 | last_working_st <= working_state_o; |
| 597 | end |
| 598 | end |
| 599 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 600 | always_comb begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 601 | state_update = 1'b1; |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 602 | working_state_o = StInvalid; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 603 | |
| 604 | unique case (state_q) |
Timothy Chen | be2da9e | 2021-01-07 18:29:01 -0800 | [diff] [blame] | 605 | StCtrlReset, StCtrlEntropyReseed, StCtrlRandom, StCtrlRootKey: |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 606 | working_state_o = StReset; |
| 607 | |
| 608 | StCtrlInit: |
| 609 | working_state_o = StInit; |
| 610 | |
| 611 | StCtrlCreatorRootKey: |
| 612 | working_state_o = StCreatorRootKey; |
| 613 | |
| 614 | StCtrlOwnerIntKey: |
| 615 | working_state_o = StOwnerIntKey; |
| 616 | |
| 617 | StCtrlOwnerKey: |
| 618 | working_state_o = StOwnerKey; |
| 619 | |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 620 | StCtrlDisabled: |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 621 | working_state_o = StDisabled; |
| 622 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 623 | StCtrlWipe: begin |
| 624 | state_update = 1'b0; |
| 625 | working_state_o = last_working_st; |
| 626 | end |
| 627 | |
| 628 | StCtrlInvalid: |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 629 | working_state_o = StInvalid; |
| 630 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 631 | default: |
Timothy Chen | 71779e1 | 2021-01-06 12:09:57 -0800 | [diff] [blame] | 632 | working_state_o = StInvalid; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame] | 633 | endcase // unique case (state_q) |
| 634 | end |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 635 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 636 | |
| 637 | ///////////////////////// |
| 638 | // Operateion state, handle advance and generate |
| 639 | ///////////////////////// |
| 640 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 641 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 642 | if (!rst_ni) begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 643 | op_state_q <= StIdle; |
Timothy Chen | eb7bf61 | 2021-08-03 16:17:09 -0700 | [diff] [blame] | 644 | end else begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 645 | op_state_q <= op_state_d; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 646 | end |
| 647 | end |
| 648 | |
| 649 | always_comb begin |
| 650 | op_state_d = op_state_q; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 651 | op_update = 1'b0; |
| 652 | op_ack = 1'b0; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 653 | op_busy = 1'b1; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 654 | |
| 655 | // output to kmac interface |
| 656 | adv_en_o = 1'b0; |
| 657 | id_en_o = 1'b0; |
| 658 | gen_en_o = 1'b0; |
| 659 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 660 | unique case (op_state_q) |
| 661 | StIdle: begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 662 | op_busy = '0; |
| 663 | if (adv_req || dis_req) begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 664 | op_state_d = StAdv; |
| 665 | end else if (id_req || gen_req) begin |
| 666 | op_state_d = StWait; |
| 667 | end |
| 668 | end |
| 669 | |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 670 | StAdv: begin |
| 671 | adv_en_o = 1'b1; |
| 672 | |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 673 | if (kmac_done_i && (cdi_cnt == CDIs-1)) begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 674 | op_ack = 1'b1; |
| 675 | op_state_d = StIdle; |
Timothy Chen | 1a16211 | 2021-06-30 18:35:59 -0700 | [diff] [blame] | 676 | end else if (kmac_done_i && (cdi_cnt < CDIs-1)) begin |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 677 | op_update = 1'b1; |
| 678 | op_state_d = StAdvAck; |
| 679 | end |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 680 | end |
| 681 | |
| 682 | // drop adv_en_o to allow kmac interface handshake |
| 683 | StAdvAck: begin |
| 684 | op_state_d = StAdv; |
| 685 | end |
| 686 | |
| 687 | // Not an advanced operation |
| 688 | StWait: begin |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 689 | id_en_o = gen_id_op; |
| 690 | gen_en_o = gen_sw_op | gen_hw_op; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 691 | |
| 692 | if (kmac_done_i) begin |
| 693 | op_ack = 1'b1; |
| 694 | op_state_d = StIdle; |
| 695 | end |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 696 | end |
| 697 | |
| 698 | // What should go here? |
| 699 | default:; |
| 700 | |
| 701 | endcase // unique case (adv_state_q) |
| 702 | end |
| 703 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 704 | // operations fsm update precedence |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 705 | // when in invalid state, always update. |
| 706 | // when in disabled state, always update unless a fault is encountered. |
| 707 | assign op_update_sel = (op_ack | op_update) & invalid ? KeyUpdateKmac : |
Timothy Chen | d02fba7 | 2021-09-01 22:49:21 -0700 | [diff] [blame] | 708 | (op_ack | op_update) & op_fault_err ? KeyUpdateWipe : |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 709 | (op_ack | op_update) & disabled ? KeyUpdateKmac : |
Timothy Chen | d02fba7 | 2021-09-01 22:49:21 -0700 | [diff] [blame] | 710 | (op_ack | op_update) & op_err ? KeyUpdateIdle : |
| 711 | (op_ack | op_update) ? KeyUpdateKmac : KeyUpdateIdle; |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 712 | |
Timothy Chen | 80fb8f4 | 2021-08-02 14:36:28 -0700 | [diff] [blame] | 713 | |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 714 | // Advance calls are made up of multiple rounds of kmac operations. |
| 715 | // Any sync error that occurs is treated as an error of the entire call. |
| 716 | // Therefore sync errors that happen before the end of the call must be |
| 717 | // latched. |
| 718 | logic[SyncErrLastIdx-1:0] sync_err_q, sync_err_d; |
| 719 | logic[SyncFaultLastIdx-1:0] sync_fault_q, sync_fault_d; |
| 720 | |
| 721 | logic err_vld; |
| 722 | assign err_vld = op_update | op_done_o; |
| 723 | |
| 724 | // sync errors |
| 725 | // When an operation encounters a fault, the operation is always rejected as the FSM |
Timothy Chen | d02fba7 | 2021-09-01 22:49:21 -0700 | [diff] [blame] | 726 | // transitions to wipe. When an operation is ongoing and en drops, it is also rejected. |
Timothy Chen | d86f385 | 2021-09-08 16:03:38 -0700 | [diff] [blame] | 727 | assign sync_err_d[SyncErrInvalidOp] = err_vld & (invalid_op | disabled | invalid | op_fault_err); |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 728 | assign sync_err_d[SyncErrInvalidIn] = err_vld & kmac_input_invalid_i; |
| 729 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 730 | if (!rst_ni) begin |
| 731 | sync_err_q <= '0; |
| 732 | end else if (op_done_o) begin |
| 733 | sync_err_q <= '0; |
| 734 | end else if (op_update) begin |
| 735 | sync_err_q <= sync_err_d; |
| 736 | end |
| 737 | end |
| 738 | assign sync_err = sync_err_q | sync_err_d; |
| 739 | |
| 740 | // async errors |
| 741 | assign async_err[AsyncErrShadowUpdate] = shadowed_update_err_i; |
| 742 | |
| 743 | // sync faults |
| 744 | assign sync_fault_d[SyncFaultKmacOp] = err_vld & kmac_op_err_i; |
| 745 | assign sync_fault_d[SyncFaultKmacOut] = err_vld & invalid_kmac_out; |
| 746 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 747 | if (!rst_ni) begin |
| 748 | sync_fault_q <= '0; |
| 749 | end else if (op_update) begin |
| 750 | sync_fault_q <= sync_fault_d; |
| 751 | end |
| 752 | end |
| 753 | assign sync_fault = sync_fault_q | sync_fault_d; |
| 754 | |
| 755 | // async faults |
Timothy Chen | a8527ca | 2021-09-15 15:45:42 -0700 | [diff] [blame] | 756 | logic [AsyncFaultLastIdx-1:0] async_fault_q, async_fault_d; |
| 757 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 758 | if (!rst_ni) begin |
| 759 | async_fault_q <= '0; |
| 760 | end else begin |
| 761 | async_fault_q <= async_fault; |
| 762 | end |
| 763 | end |
| 764 | assign async_fault = async_fault_q | async_fault_d; |
| 765 | assign async_fault_d[AsyncFaultKmacCmd] = kmac_cmd_err_i; |
| 766 | assign async_fault_d[AsyncFaultKmacFsm] = kmac_fsm_err_i; |
| 767 | assign async_fault_d[AsyncFaultRegIntg] = regfile_intg_err_i; |
| 768 | assign async_fault_d[AsyncFaultShadow ] = shadowed_storage_err_i; |
| 769 | assign async_fault_d[AsyncFaultFsmIntg] = state_intg_err_q; |
| 770 | assign async_fault_d[AsyncFaultCntErr ] = cnt_err; |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 771 | |
| 772 | // output to error code register |
| 773 | assign error_o[ErrInvalidOp] = op_done_o & sync_err[SyncErrInvalidOp]; |
| 774 | assign error_o[ErrInvalidIn] = op_done_o & sync_err[SyncErrInvalidIn]; |
| 775 | assign error_o[ErrShadowUpdate] = async_err[AsyncErrShadowUpdate]; |
| 776 | |
| 777 | // output to fault code register |
| 778 | assign fault_o[FaultKmacOp] = op_done_o & sync_fault[SyncFaultKmacOp]; |
| 779 | assign fault_o[FaultKmacOut] = op_done_o & sync_fault[SyncFaultKmacOut]; |
| 780 | assign fault_o[FaultKmacCmd] = async_fault[AsyncFaultKmacCmd]; |
| 781 | assign fault_o[FaultKmacFsm] = async_fault[AsyncFaultKmacFsm]; |
| 782 | assign fault_o[FaultRegIntg] = async_fault[AsyncFaultRegIntg]; |
| 783 | assign fault_o[FaultShadow] = async_fault[AsyncFaultShadow]; |
| 784 | assign fault_o[FaultCtrlFsm] = async_fault[AsyncFaultFsmIntg]; |
| 785 | assign fault_o[FaultCtrlCnt] = async_fault[AsyncFaultCntErr]; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 786 | |
| 787 | always_comb begin |
| 788 | status_o = OpIdle; |
| 789 | if (op_done_o) begin |
Timothy Chen | 28bbd32 | 2021-09-01 00:06:10 -0700 | [diff] [blame] | 790 | status_o = |error_o | |fault_o ? OpDoneFail : OpDoneSuccess; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 791 | end else if (op_start_i) begin |
| 792 | status_o = OpWip; |
| 793 | end |
| 794 | end |
| 795 | |
| 796 | |
Timothy Chen | 8cf1a3a | 2020-12-08 19:05:29 -0800 | [diff] [blame] | 797 | /////////////////////////////// |
| 798 | // Suppress kmac return data |
| 799 | /////////////////////////////// |
| 800 | // This is a separate data path from the FSM used to control the data_en_o output |
| 801 | |
| 802 | typedef enum logic [1:0] { |
| 803 | StCtrlDataIdle, |
| 804 | StCtrlDataEn, |
| 805 | StCtrlDataDis, |
| 806 | StCtrlDataWait |
| 807 | } keymgr_ctrl_data_state_e; |
| 808 | |
| 809 | keymgr_ctrl_data_state_e data_st_d, data_st_q; |
| 810 | |
| 811 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 812 | if (!rst_ni) begin |
| 813 | data_st_q <= StCtrlDataIdle; |
| 814 | end else begin |
| 815 | data_st_q <= data_st_d; |
| 816 | end |
| 817 | end |
| 818 | |
| 819 | // The below control path is used for modulating the datapath to sideload and sw keys. |
| 820 | // This path is separate from the data_valid_o path, thus creating two separate attack points. |
| 821 | // The data is only enabled when a non-advance operation is invoked. |
| 822 | // When an advance operation is called, the data is disabled. It will stay disabled until an |
| 823 | // entire completion sequence is seen (op_done_o assert -> start_i de-assertion). |
| 824 | // When a generate operation is called, the data is enabled. However, any indication of this |
| 825 | // supposedly being an advance call will force the path to disable again. |
| 826 | always_comb begin |
| 827 | data_st_d = data_st_q; |
| 828 | data_en_o = 1'b0; |
| 829 | unique case (data_st_q) |
| 830 | |
| 831 | StCtrlDataIdle: begin |
| 832 | if (adv_en_o) begin |
| 833 | data_st_d = StCtrlDataDis; |
| 834 | end else if (id_en_o || gen_en_o) begin |
| 835 | data_st_d = StCtrlDataEn; |
| 836 | end |
| 837 | end |
| 838 | |
| 839 | StCtrlDataEn: begin |
| 840 | data_en_o = 1'b1; |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 841 | if (op_done_o) begin |
| 842 | data_st_d = StCtrlDataWait; |
| 843 | end else if (adv_en_o) begin |
Timothy Chen | 8cf1a3a | 2020-12-08 19:05:29 -0800 | [diff] [blame] | 844 | data_st_d = StCtrlDataDis; |
| 845 | end |
| 846 | end |
| 847 | |
| 848 | StCtrlDataDis: begin |
| 849 | if (op_done_o) begin |
| 850 | data_st_d = StCtrlDataWait; |
| 851 | end |
| 852 | end |
| 853 | |
| 854 | StCtrlDataWait: begin |
| 855 | if (!op_start_i) begin |
| 856 | data_st_d = StCtrlDataIdle; |
| 857 | end |
| 858 | end |
| 859 | |
| 860 | default:; |
| 861 | |
| 862 | endcase // unique case (data_st_q) |
| 863 | end |
| 864 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 865 | /////////////////////////////// |
| 866 | // Functions |
| 867 | /////////////////////////////// |
| 868 | |
| 869 | // unclear what this is supposed to be yet |
| 870 | // right now just check to see if it not all 0's and not all 1's |
Timothy Chen | ae05e94 | 2020-12-21 21:09:57 -0800 | [diff] [blame] | 871 | function automatic logic valid_data_chk (logic [KeyWidth-1:0] value); |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 872 | |
| 873 | return |value & ~&value; |
| 874 | |
| 875 | endfunction // byte_mask |
| 876 | |
Timothy Chen | ae05e94 | 2020-12-21 21:09:57 -0800 | [diff] [blame] | 877 | ///////////////////////////////// |
| 878 | // Assertions |
| 879 | ///////////////////////////////// |
| 880 | |
| 881 | // stage select should always be Disable whenever it is not enabled |
| 882 | `ASSERT(StageDisableSel_A, !en_i |-> stage_sel_o == Disable) |
| 883 | |
| 884 | // Unless it is a legal command, only select disable |
| 885 | `ASSERT(InitLegalCommands_A, op_start_i & en_i & state_q inside {StCtrlInit} & |
| 886 | !(op_i inside {OpAdvance}) |-> stage_sel_o == Disable) |
| 887 | |
| 888 | // All commands are legal, so select disable only if operation is disable |
| 889 | `ASSERT(GeneralLegalCommands_A, op_start_i & en_i & |
| 890 | state_q inside {StCtrlCreatorRootKey, StCtrlOwnerIntKey} & |
| 891 | (op_i inside {OpDisable}) |-> stage_sel_o == Disable) |
| 892 | |
| 893 | `ASSERT(OwnerLegalCommands_A, op_start_i & en_i & state_q inside {StCtrlOwnerKey} & |
| 894 | (op_i inside {OpAdvance, OpDisable}) |-> stage_sel_o == Disable) |
| 895 | |
Timothy Chen | 77758a6 | 2021-01-12 18:45:47 -0800 | [diff] [blame] | 896 | // load_key should not be high if there is no ongoing operation |
Timothy Chen | 3803324 | 2021-06-29 10:06:12 -0700 | [diff] [blame] | 897 | `ASSERT(LoadKey_A, key_o.valid |-> op_start_i) |
| 898 | |
| 899 | // The count value should always be 0 when a transaction start |
| 900 | `ASSERT(CntZero_A, $rose(op_start_i) |-> cnt == '0) |
Timothy Chen | 77758a6 | 2021-01-12 18:45:47 -0800 | [diff] [blame] | 901 | |
Timothy Chen | 8e37434 | 2021-08-25 20:55:31 -0700 | [diff] [blame] | 902 | // Whenever a transaction completes, data_en must return to 0 on the next cycle |
| 903 | `ASSERT(DataEnDis_A, op_start_i & op_done_o |=> ~data_en_o) |
| 904 | |
| 905 | // Whenever data enable asserts, it must be the case that there was a generate or |
| 906 | // id operation |
| 907 | `ASSERT(DataEn_A, data_en_o |-> (id_en_o | gen_en_o) & ~adv_en_o) |
| 908 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 909 | endmodule |