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 | |
| 10 | module keymgr_ctrl import keymgr_pkg::*;( |
| 11 | input clk_i, |
| 12 | input rst_ni, |
| 13 | |
| 14 | // lifecycle enforcement |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 15 | input en_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 16 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 17 | // Software interface |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 18 | input op_start_i, |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 19 | input keymgr_ops_e op_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 20 | output logic op_done_o, |
| 21 | output keymgr_op_status_e status_o, |
| 22 | output logic [ErrLastPos-1:0] error_o, |
| 23 | output logic data_valid_o, |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 24 | output logic wipe_key_o, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 25 | output keymgr_working_state_e working_state_o, |
| 26 | |
| 27 | // Data input |
Timothy Chen | 65e1667 | 2020-12-05 09:17:14 -0800 | [diff] [blame] | 28 | input otp_ctrl_pkg::otp_keymgr_key_t root_key_i, |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 29 | output keymgr_gen_out_e hw_sel_o, |
| 30 | output keymgr_stage_e stage_sel_o, |
| 31 | |
| 32 | // KMAC ctrl interface |
| 33 | output logic adv_en_o, |
| 34 | output logic id_en_o, |
| 35 | output logic gen_en_o, |
| 36 | output logic [Shares-1:0][KeyWidth-1:0] key_o, |
| 37 | output logic load_key_o, |
| 38 | input kmac_done_i, |
| 39 | input kmac_input_invalid_i, // asserted when selected data fails criteria check |
| 40 | input kmac_fsm_err_i, // asserted when kmac fsm reaches unexpected state |
Timothy Chen | eaa3f2b | 2020-10-27 17:10:15 -0700 | [diff] [blame] | 41 | input kmac_op_err_i, // asserted when kmac itself reports an error |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 42 | 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] | 43 | input [Shares-1:0][KeyWidth-1:0] kmac_data_i, |
| 44 | |
| 45 | // prng control interface |
| 46 | input [(LfsrWidth/2)-1:0] entropy_i, |
| 47 | input prng_reseed_ack_i, |
| 48 | output logic prng_reseed_req_o, |
| 49 | output logic prng_en_o |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 50 | ); |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 51 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 52 | localparam int EntropyWidth = LfsrWidth / 2; |
| 53 | localparam int EntropyRounds = KeyWidth / EntropyWidth; |
| 54 | localparam int CntWidth = $clog2(EntropyRounds + 1); |
| 55 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 56 | // Enumeration for working state |
| 57 | typedef enum logic [3:0] { |
| 58 | StCtrlReset = 0, |
| 59 | StCtrlEntropyReseed = 1, |
| 60 | StCtrlRandom = 2, |
| 61 | StCtrlInit = 3, |
| 62 | StCtrlCreatorRootKey = 4, |
| 63 | StCtrlOwnerIntKey = 5, |
| 64 | StCtrlOwnerKey = 6, |
| 65 | StCtrlWipe = 7, |
| 66 | StCtrlDisabled = 8 |
| 67 | } keymgr_ctrl_state_e; |
| 68 | |
| 69 | keymgr_ctrl_state_e state_q, state_d; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 70 | logic [Shares-1:0][EntropyRounds-1:0][EntropyWidth-1:0] key_state_q, key_state_d; |
| 71 | |
| 72 | logic [CntWidth-1:0] cnt; |
| 73 | logic cnt_en; |
| 74 | logic cnt_clr; |
| 75 | logic data_valid; |
| 76 | logic adv_en_q; |
| 77 | logic op_accepted; |
| 78 | logic invalid_op; |
| 79 | |
| 80 | // disable is treated like an advanced call |
| 81 | logic advance_sel; |
| 82 | logic disable_sel; |
| 83 | logic gen_id_sel; |
| 84 | logic gen_out_sw_sel; |
| 85 | logic gen_out_hw_sel; |
| 86 | logic gen_out_sel; |
| 87 | logic gen_sel; |
| 88 | |
| 89 | // something went wrong with the kmac interface operation |
| 90 | logic kmac_op_err; |
| 91 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 92 | assign advance_sel = op_start_i & op_i == OpAdvance & en_i; |
| 93 | assign gen_id_sel = op_start_i & op_i == OpGenId & en_i; |
| 94 | assign gen_out_sw_sel = op_start_i & op_i == OpGenSwOut & en_i; |
| 95 | assign gen_out_hw_sel = op_start_i & op_i == OpGenHwOut & en_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 96 | assign gen_out_sel = gen_out_sw_sel | gen_out_hw_sel; |
| 97 | assign gen_sel = gen_id_sel | gen_out_sel; |
| 98 | |
| 99 | // disable is selected whenever a normal operation is not, and when |
| 100 | // keymgr is disabled |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 101 | assign disable_sel = (op_start_i & !(gen_sel | advance_sel)) | |
| 102 | !en_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 103 | |
| 104 | assign adv_en_o = op_accepted & (advance_sel | disable_sel); |
| 105 | assign id_en_o = op_accepted & gen_id_sel; |
| 106 | assign gen_en_o = op_accepted & gen_out_sel; |
| 107 | assign load_key_o = adv_en_o & !adv_en_q; |
| 108 | |
| 109 | // check incoming kmac data validity |
| 110 | // also check inputs used during compute |
| 111 | assign data_valid = valid_data_chk(kmac_data_i[0]) & valid_data_chk(kmac_data_i[1]) |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 112 | & !kmac_input_invalid_i & !kmac_op_err; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 113 | |
| 114 | // Unlike the key state, the working state can be safely reset. |
| 115 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 116 | if (!rst_ni) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 117 | state_q <= StCtrlReset; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 118 | adv_en_q <= 1'b0; |
| 119 | end else begin |
| 120 | state_q <= state_d; |
| 121 | adv_en_q <= adv_en_o; |
| 122 | end |
| 123 | end |
| 124 | |
| 125 | // prevents unknowns from reaching the outside world. |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 126 | // - whatever operation causes the input data select to be disabled should not expose the key |
| 127 | // state. |
| 128 | // - when there are no operations, the key state also should be exposed. |
| 129 | assign key_o = (~op_start_i | disable_sel) ? {EntropyRounds * Shares {entropy_i}} : key_state_q; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 130 | |
| 131 | // key state is intentionally not reset |
| 132 | always_ff @(posedge clk_i) begin |
| 133 | key_state_q <= key_state_d; |
| 134 | end |
| 135 | |
| 136 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 137 | if (!rst_ni) begin |
| 138 | cnt <= '0; |
| 139 | end else if (cnt_clr) begin |
| 140 | cnt <= '0; |
| 141 | end else if (cnt_en) begin |
| 142 | cnt <= cnt + 1'b1; |
| 143 | end |
| 144 | end |
| 145 | |
Timothy Chen | eaa3f2b | 2020-10-27 17:10:15 -0700 | [diff] [blame] | 146 | assign kmac_op_err = kmac_cmd_err_i | kmac_fsm_err_i | kmac_op_err_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 147 | |
Timothy Chen | 65e1667 | 2020-12-05 09:17:14 -0800 | [diff] [blame] | 148 | // root key valid sync |
| 149 | logic root_key_valid_q; |
| 150 | |
| 151 | prim_flop_2sync # ( |
| 152 | .Width(1) |
| 153 | ) u_key_valid_sync ( |
| 154 | .clk_i, |
| 155 | .rst_ni, |
| 156 | .d_i(root_key_i.valid), |
| 157 | .q_o(root_key_valid_q) |
| 158 | ); |
| 159 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 160 | // TODO: Create a no select option, do not leave this as binary |
| 161 | assign hw_sel_o = gen_out_hw_sel ? HwKey : SwKey; |
| 162 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 163 | always_comb begin |
| 164 | // persistent data |
| 165 | state_d = state_q; |
| 166 | key_state_d = key_state_q; |
| 167 | |
| 168 | // locally consumed select signals |
| 169 | cnt_en = 1'b0; |
| 170 | cnt_clr = 1'b0; |
| 171 | op_accepted = 1'b0; |
| 172 | invalid_op = 1'b0; |
| 173 | |
| 174 | // data update and select signals |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 175 | stage_sel_o = Disable; |
| 176 | |
| 177 | // enable prng toggling |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 178 | prng_reseed_req_o = 1'b0; |
Timothy Chen | 4a97f3b | 2020-11-11 17:36:31 -0800 | [diff] [blame] | 179 | prng_en_o = 1'b0; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 180 | |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 181 | op_done_o = 1'b0; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 182 | wipe_key_o = 1'b0; |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 183 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 184 | unique case (state_q) |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 185 | // Only advance can be called from reset state |
| 186 | StCtrlReset: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 187 | // in reset state, don't enable entropy yet, since there are no users. |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 188 | prng_en_o = 1'b0; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 189 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 190 | // always use random data for advance, since out of reset state |
| 191 | // the key state will be randomized. |
| 192 | stage_sel_o = Disable; |
| 193 | |
| 194 | // key state is updated when it is an advance call |
| 195 | // all other operations are invalid, including disable |
| 196 | if (advance_sel) begin |
| 197 | state_d = StCtrlEntropyReseed; |
| 198 | end else if (op_start_i) begin |
| 199 | op_done_o = 1'b1; |
| 200 | invalid_op = 1'b1; |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 201 | end |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 202 | end |
| 203 | |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 204 | // reseed entropy |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 205 | StCtrlEntropyReseed: begin |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 206 | prng_reseed_req_o = 1'b1; |
| 207 | if (prng_reseed_ack_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 208 | state_d = StCtrlRandom; |
Timothy Chen | d5820b0 | 2020-12-05 17:19:06 -0800 | [diff] [blame] | 209 | end |
| 210 | end |
| 211 | |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 212 | // This state does not accept any command. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 213 | StCtrlRandom: begin |
Timothy Chen | 4a97f3b | 2020-11-11 17:36:31 -0800 | [diff] [blame] | 214 | prng_en_o = 1'b1; |
| 215 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 216 | // populate both shares with the same entropy |
| 217 | // This is the default mask |
| 218 | if (cnt < EntropyRounds) begin |
| 219 | cnt_en = 1'b1; |
| 220 | for (int i = 0; i < Shares; i++) begin |
| 221 | key_state_d[i][cnt] = entropy_i; |
| 222 | end |
| 223 | end |
| 224 | // when mask population is complete, xor the root_key into the zero share |
| 225 | // if in the future the root key is updated to 2 shares, it will direclty overwrite |
| 226 | // the values here |
| 227 | else begin |
| 228 | cnt_clr = 1'b1; |
Timothy Chen | 65e1667 | 2020-12-05 09:17:14 -0800 | [diff] [blame] | 229 | |
| 230 | // absorb key if valid, otherwise use entropy |
| 231 | if (root_key_valid_q) begin |
| 232 | key_state_d[0] = root_key_i.key_share0; |
| 233 | key_state_d[1] = root_key_i.key_share1; |
| 234 | end |
| 235 | |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 236 | op_done_o = 1'b1; |
| 237 | state_d = StCtrlInit; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 238 | end |
| 239 | end |
| 240 | |
| 241 | // Beginning from the Init state, operations are accepted. |
| 242 | // Only valid operation is advance state. If invalid command received, |
| 243 | // random data is selected for operation and no persistent state is changed. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 244 | StCtrlInit: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 245 | op_done_o = op_start_i & kmac_done_i; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 246 | op_accepted = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 247 | |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 248 | // when advancing select creator data, otherwise use random input |
| 249 | stage_sel_o = advance_sel ? Creator : Disable; |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 250 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 251 | // key state is updated when it is an advance call |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 252 | if (!en_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 253 | state_d = StCtrlWipe; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 254 | end else if (op_done_o && (disable_sel || kmac_op_err)) begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 255 | key_state_d = kmac_data_i; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 256 | state_d = StCtrlDisabled; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 257 | end else if (op_done_o && advance_sel) begin |
| 258 | key_state_d = data_valid ? kmac_data_i : key_state_q; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 259 | state_d = StCtrlCreatorRootKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 260 | end else if (op_done_o) begin |
| 261 | invalid_op = 1'b1; |
| 262 | end |
| 263 | end |
| 264 | |
| 265 | // all commands are valid during this stage |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 266 | StCtrlCreatorRootKey: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 267 | op_done_o = op_start_i & kmac_done_i; |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 268 | op_accepted = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 269 | |
| 270 | // when generating, select creator data input |
| 271 | // when advancing, select owner intermediate key as target |
| 272 | // when disabling, select random data input |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 273 | stage_sel_o = disable_sel ? Disable : |
| 274 | advance_sel ? OwnerInt : Creator; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 275 | |
| 276 | // key state is updated when it is an advance call |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 277 | if (!en_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 278 | state_d = StCtrlWipe; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 279 | end else if (op_done_o && (disable_sel || kmac_op_err)) begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 280 | key_state_d = kmac_data_i; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 281 | state_d = StCtrlDisabled; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 282 | end else if (op_done_o && advance_sel) begin |
| 283 | key_state_d = data_valid ? kmac_data_i : key_state_q; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 284 | state_d = StCtrlOwnerIntKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 285 | end |
| 286 | end |
| 287 | |
| 288 | |
| 289 | // all commands are valid during this stage |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 290 | StCtrlOwnerIntKey: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 291 | op_done_o = op_start_i & kmac_done_i; |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 292 | op_accepted = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 293 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 294 | // when generating, select owner intermediate data input |
| 295 | // when advancing, select owner as target |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 296 | // when disabling, select random data input |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 297 | stage_sel_o = disable_sel ? Disable : |
| 298 | advance_sel ? Owner : OwnerInt; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 299 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 300 | if (!en_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 301 | state_d = StCtrlWipe; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 302 | end else if (op_done_o && (disable_sel || kmac_op_err)) begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 303 | key_state_d = kmac_data_i; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 304 | state_d = StCtrlDisabled; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 305 | end else if (op_done_o && advance_sel) begin |
| 306 | key_state_d = data_valid ? kmac_data_i : key_state_q; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 307 | state_d = StCtrlOwnerKey; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 308 | end |
| 309 | end |
| 310 | |
| 311 | // all commands are valid during this stage |
| 312 | // however advance goes directly to disabled state |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 313 | StCtrlOwnerKey: begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 314 | op_done_o = op_start_i & kmac_done_i; |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 315 | op_accepted = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 316 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 317 | // when generating, select owner data input |
| 318 | // when advancing, select disable as target |
| 319 | // when disabling, select random data input |
Timothy Chen | 68c311a | 2020-12-04 12:31:17 -0800 | [diff] [blame] | 320 | stage_sel_o = disable_sel | advance_sel ? Disable : Owner; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 321 | |
| 322 | // Calling advanced from ownerKey also leads to disable |
| 323 | // Thus data_valid is not checked |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 324 | if (!en_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 325 | state_d = StCtrlWipe; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 326 | end else if (op_done_o && (advance_sel || disable_sel || kmac_op_err)) begin |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 327 | key_state_d = kmac_data_i; |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 328 | state_d = StCtrlDisabled; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 329 | end |
| 330 | end |
| 331 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 332 | // The wipe state immediately clears out the key state, but waits for any ongoing |
| 333 | // transaction to finish before going to disabled state. |
| 334 | // Unlike the random state, this is an immedaite shutdown request, so all parts of the |
| 335 | // key are wiped. |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 336 | StCtrlWipe: begin |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 337 | stage_sel_o = Disable; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 338 | op_done_o = op_start_i & kmac_done_i; |
| 339 | op_accepted = op_start_i; |
| 340 | wipe_key_o = 1'b1; |
| 341 | |
| 342 | for (int i = 0; i < Shares; i++) begin |
| 343 | key_state_d[i] = {EntropyRounds{entropy_i}}; |
| 344 | end |
| 345 | |
| 346 | // If the enable is dropped during the middle of a transaction, we clear and wait for that |
| 347 | // transaction to gracefully complete (if it can). |
| 348 | // There are two scenarios: |
| 349 | // 1. the operation completed right when we started wiping, in which case the done would |
| 350 | // clear the start. |
| 351 | // 2. the operation completed before we started wiping, or there was never an operation to |
| 352 | // begin with (op_start_i == 0), in this case, don't wait and immediately transition |
| 353 | if (!op_start_i) begin |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 354 | state_d = StCtrlDisabled; |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 355 | end |
| 356 | end |
| 357 | |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 358 | // Terminal state (StDisabled is included) |
| 359 | // However, it will continue to kick off dummy transactions |
| 360 | default: begin |
| 361 | op_done_o = op_start_i & kmac_done_i; |
| 362 | |
| 363 | // accept any command, but always select fake data |
| 364 | op_accepted = op_start_i; |
| 365 | stage_sel_o = Disable; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 366 | |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 367 | // During disabled state, continue to update state |
| 368 | key_state_d = (op_done_o && advance_sel) ? kmac_data_i : key_state_q; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 369 | |
| 370 | // Despite accepting all commands, operations are always |
| 371 | // considered invalid in disabled state |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 372 | // TODO this may be changed later if we decide to hide disable state from |
Timothy Chen | 1d05bd6 | 2020-10-07 18:42:07 -0700 | [diff] [blame] | 373 | // software. |
| 374 | invalid_op = op_start_i; |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 375 | end |
| 376 | |
| 377 | endcase // unique case (state_q) |
| 378 | end |
| 379 | |
| 380 | |
| 381 | // Current working state provided for software read |
Timothy Chen | 9e36545 | 2020-12-07 19:04:00 -0800 | [diff] [blame^] | 382 | // Certain states are collapsed for simplicity |
| 383 | always_comb begin |
| 384 | working_state_o = StDisabled; |
| 385 | |
| 386 | unique case (state_q) |
| 387 | StCtrlReset, StCtrlEntropyReseed, StCtrlRandom: |
| 388 | working_state_o = StReset; |
| 389 | |
| 390 | StCtrlInit: |
| 391 | working_state_o = StInit; |
| 392 | |
| 393 | StCtrlCreatorRootKey: |
| 394 | working_state_o = StCreatorRootKey; |
| 395 | |
| 396 | StCtrlOwnerIntKey: |
| 397 | working_state_o = StOwnerIntKey; |
| 398 | |
| 399 | StCtrlOwnerKey: |
| 400 | working_state_o = StOwnerKey; |
| 401 | |
| 402 | StCtrlWipe, StCtrlDisabled: |
| 403 | working_state_o = StDisabled; |
| 404 | |
| 405 | default: |
| 406 | working_state_o = StDisabled; |
| 407 | endcase // unique case (state_q) |
| 408 | end |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 409 | |
Timothy Chen | 6d99c34 | 2020-11-13 12:02:42 -0800 | [diff] [blame] | 410 | // if operation was never accepted (ie a generate was called in StReset / StRandom), then |
Timothy Chen | 15adeee | 2020-09-09 15:44:35 -0700 | [diff] [blame] | 411 | // never update the sw / hw outputs when operation is complete |
| 412 | assign data_valid_o = op_done_o & op_accepted & data_valid & gen_sel; |
| 413 | |
| 414 | // data errors are not relevant when operation was not accepted. |
| 415 | assign error_o[ErrInvalidOp] = invalid_op; |
| 416 | assign error_o[ErrInvalidCmd] = op_start_i & op_accepted & kmac_op_err; |
| 417 | assign error_o[ErrInvalidIn] = op_done_o & op_accepted & kmac_input_invalid_i; |
| 418 | assign error_o[ErrInvalidOut] = op_done_o & op_accepted & ~data_valid; |
| 419 | |
| 420 | always_comb begin |
| 421 | status_o = OpIdle; |
| 422 | if (op_done_o) begin |
| 423 | status_o = |error_o ? OpDoneFail : OpDoneSuccess; |
| 424 | end else if (op_start_i) begin |
| 425 | status_o = OpWip; |
| 426 | end |
| 427 | end |
| 428 | |
| 429 | |
| 430 | |
| 431 | /////////////////////////////// |
| 432 | // Functions |
| 433 | /////////////////////////////// |
| 434 | |
| 435 | // unclear what this is supposed to be yet |
| 436 | // right now just check to see if it not all 0's and not all 1's |
| 437 | function automatic logic valid_data_chk (logic [KeyWidth-1:0] value); |
| 438 | |
| 439 | return |value & ~&value; |
| 440 | |
| 441 | endfunction // byte_mask |
| 442 | |
| 443 | endmodule |