From a48bff7780f11f822abf5cd9a0c9ba69d4f0f6af Mon Sep 17 00:00:00 2001 From: Pirmin Vogel Date: Mon, 13 May 2024 09:24:08 +0200 Subject: [PATCH] [keymgr] Don't update and reseed PRNG in Disabled/Invalid state forever Previously, keymgr would keep updating and reseeding the PRNG forever once entering the StCtrlDisabled or StCtrlInvalid state. This is not ideal from an entropy and power consumption viewpoint. This commit changes the design to - once one of the two states is entered - to keep updating the PRNG (which also triggers the reseed operation) until two more PRNG reseed operation have happened. This also includes the keymgr_DPE specific changes of lowRISC/OpenTitan#23071. This is related to lowRISC/OpenTitan#22997. Signed-off-by: Pirmin Vogel --- hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv | 3 +++ hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv | 31 +++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv b/hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv index ecbc767ec979c4..9a31f6a5500691 100644 --- a/hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv +++ b/hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv @@ -179,6 +179,7 @@ module keymgr_dpe logic [LfsrWidth-1:0] seed; logic reseed_req; logic reseed_ack; + logic reseed_done; logic reseed_cnt_err; keymgr_reseed_ctrl u_reseed_ctrl ( @@ -188,6 +189,7 @@ module keymgr_dpe .rst_edn_ni, .reseed_req_i(reseed_req), .reseed_ack_o(reseed_ack), + .reseed_done_o(reseed_done), .reseed_interval_i(reg2hw.reseed_interval_shadowed.q), .edn_o, .edn_i, @@ -292,6 +294,7 @@ module keymgr_dpe .sideload_fsm_err_i(sideload_fsm_err), .prng_reseed_req_o(reseed_req), .prng_reseed_ack_i(reseed_ack), + .prng_reseed_done_i(reseed_done), .prng_en_o(ctrl_lfsr_en), .entropy_i(ctrl_rand), .op_i(keymgr_dpe_ops_e'(reg2hw.control_shadowed.operation.q)), diff --git a/hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv b/hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv index 8d045cdb4a8011..e41bc72d67447a 100644 --- a/hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv +++ b/hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv @@ -78,6 +78,7 @@ module keymgr_dpe_ctrl // prng control interface input [Shares-1:0][RandWidth-1:0] entropy_i, + input prng_reseed_done_i, input prng_reseed_ack_i, output logic prng_reseed_req_o, output logic prng_en_o @@ -210,7 +211,24 @@ module keymgr_dpe_ctrl // interaction between main fsm and prng /////////////////////////// - assign prng_en_o = random_req | fsm_at_disabled | fsm_at_invalid | wipe_req; + // Upon entering StCtrlDisabled or StCtrlInvalid, the PRNG is kept advancing until it has been + // reseeded twice (through the reseeding mechansism inside keymgr_reseed_ctrl.sv). + logic [1:0] prng_en_dis_inv_d, prng_en_dis_inv_q; + logic prng_en_dis_inv_set; + + assign prng_en_dis_inv_d = + prng_en_dis_inv_set ? 2'b11 : + prng_reseed_done_i ? {1'b0, prng_en_dis_inv_q[1]} : prng_en_dis_inv_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + prng_en_dis_inv_q <= '0; + end else begin + prng_en_dis_inv_q <= prng_en_dis_inv_d; + end + end + + assign prng_en_o = random_req | wipe_req | prng_en_dis_inv_q[0]; ////////////////////////// // Main Control FSM @@ -411,7 +429,10 @@ module keymgr_dpe_ctrl // invalid operation issued invalid_op = 1'b0; - // enable prng toggling + // Don't request final PRNG updating and reseeding. + prng_en_dis_inv_set = 1'b0; + + // Request PRNG reseeding. prng_reseed_req_o = 1'b0; // signal the cycle that loads UDS @@ -431,6 +452,7 @@ module keymgr_dpe_ctrl // if there was a structural fault before anything then move to invalid directly if (inv_state) begin state_d = StCtrlDpeInvalid; + prng_en_dis_inv_set = 1'b1; end else if (advance_cmd) begin state_d = StCtrlDpeEntropyReseed; end @@ -445,6 +467,7 @@ module keymgr_dpe_ctrl invalid_op = ~en_i; if (!en_i) begin state_d = StCtrlDpeInvalid; + prng_en_dis_inv_set = 1'b1; end else if (prng_reseed_ack_i) begin state_d = StCtrlDpeRandom; end @@ -462,6 +485,7 @@ module keymgr_dpe_ctrl invalid_op = ~en_i; if (!en_i) begin state_d = StCtrlDpeInvalid; + prng_en_dis_inv_set = 1'b1; end else if (int'(cnt) == EntropyRounds - 1) begin random_ack = 1'b1; state_d = StCtrlDpeRootKey; @@ -479,6 +503,7 @@ module keymgr_dpe_ctrl // Since we did not store the root key, we do not have to wipe it. if (!en_i | inv_state | ~root_key_i.valid) begin state_d = StCtrlDpeInvalid; + prng_en_dis_inv_set = 1'b1; end else begin state_d = StCtrlDpeAvailable; end @@ -515,11 +540,13 @@ module keymgr_dpe_ctrl invalid_op = op_start_i; state_d = StCtrlDpeInvalid; + prng_en_dis_inv_set = 1'b1; end StCtrlDpeDisabling: begin op_req = op_start_i; state_d = StCtrlDpeDisabled; + prng_en_dis_inv_set = 1'b1; end // TODO(#384): Revisit allowing transactions during Disabled and Invalid.