Skip to content

Commit

Permalink
[aes] Randomnly advance the masking PRNG when not used during processing
Browse files Browse the repository at this point in the history
Randomly advancing the masking PRNG when it's not used during processing
is beneficial from an SCA hardening perspective as it increases noise.

Signed-off-by: Pirmin Vogel <[email protected]>
  • Loading branch information
vogelpi committed Apr 25, 2024
1 parent 2c7dc6c commit 4e738c6
Show file tree
Hide file tree
Showing 10 changed files with 443 additions and 356 deletions.
2 changes: 1 addition & 1 deletion hw/ip/aes/data/aes.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
desc: '''
Permutation applied to the output of the PRNG used for masking.
'''
randcount: "160",
randcount: "164",
randtype: "perm"
},
# Note: All parameters below are local, they are not actually configurable.
Expand Down
20 changes: 15 additions & 5 deletions hw/ip/aes/rtl/aes_cipher_control.sv
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

module aes_cipher_control import aes_pkg::*;
#(
parameter bit CiphOpFwdOnly = 0,
parameter bit SecMasking = 0,
parameter sbox_impl_e SecSBoxImpl = SBoxImplDom
parameter bit CiphOpFwdOnly = 0,
parameter bit SecMasking = 0,
parameter sbox_impl_e SecSBoxImpl = SBoxImplDom,
parameter int unsigned WidthPRD = WidthPRDAux
) (
input logic clk_i,
input logic rst_ni,
Expand Down Expand Up @@ -50,6 +51,9 @@ module aes_cipher_control import aes_pkg::*;
output logic prng_reseed_req_o,
input logic prng_reseed_ack_i,

// Pseudo-random data input
input logic [WidthPRD-1:0] prd_i,

// Control and sync signals for cipher data path
output state_sel_e state_sel_o,
output sp2v_e state_we_o,
Expand Down Expand Up @@ -153,7 +157,8 @@ module aes_cipher_control import aes_pkg::*;
if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_fsm_p
aes_cipher_control_fsm_p #(
.SecMasking ( SecMasking ),
.SecSBoxImpl ( SecSBoxImpl )
.SecSBoxImpl ( SecSBoxImpl ),
.WidthPRD ( WidthPRD )
) u_aes_cipher_control_fsm_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
Expand Down Expand Up @@ -183,6 +188,8 @@ module aes_cipher_control import aes_pkg::*;
.prng_reseed_req_o ( mr_prng_reseed_req[i] ), // OR-combine
.prng_reseed_ack_i ( prng_reseed_ack_i ),

.prd_i ( prd_i ),

.state_sel_o ( mr_state_sel[i] ), // OR-combine
.state_we_o ( sp_state_we[i] ), // Sparsified
.sub_bytes_en_o ( sp_sub_bytes_en[i] ), // Sparsified
Expand Down Expand Up @@ -216,7 +223,8 @@ module aes_cipher_control import aes_pkg::*;
end else begin : gen_fsm_n
aes_cipher_control_fsm_n #(
.SecMasking ( SecMasking ),
.SecSBoxImpl ( SecSBoxImpl )
.SecSBoxImpl ( SecSBoxImpl ),
.WidthPRD ( WidthPRD )
) u_aes_cipher_control_fsm_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
Expand Down Expand Up @@ -246,6 +254,8 @@ module aes_cipher_control import aes_pkg::*;
.prng_reseed_req_o ( mr_prng_reseed_req[i] ), // OR-combine
.prng_reseed_ack_i ( prng_reseed_ack_i ),

.prd_i ( prd_i ),

.state_sel_o ( mr_state_sel[i] ), // OR-combine
.state_we_no ( sp_state_we[i] ), // Sparsified
.sub_bytes_en_no ( sp_sub_bytes_en[i] ), // Sparsified
Expand Down
154 changes: 95 additions & 59 deletions hw/ip/aes/rtl/aes_cipher_control_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -10,73 +10,77 @@

module aes_cipher_control_fsm import aes_pkg::*;
#(
parameter bit SecMasking = 0,
parameter sbox_impl_e SecSBoxImpl = SBoxImplDom
parameter bit SecMasking = 0,
parameter sbox_impl_e SecSBoxImpl = SBoxImplDom,
parameter int unsigned WidthPRD = WidthPRDAux
) (
input logic clk_i,
input logic rst_ni,
input logic clk_i,
input logic rst_ni,

// Input handshake signals
input logic in_valid_i, // Sparsify using multi-rail.
output logic in_ready_o, // Sparsify using multi-rail.
input logic in_valid_i, // Sparsify using multi-rail.
output logic in_ready_o, // Sparsify using multi-rail.

// Output handshake signals
output logic out_valid_o, // Sparsify using multi-rail.
input logic out_ready_i, // Sparsify using multi-rail.
output logic out_valid_o, // Sparsify using multi-rail.
input logic out_ready_i, // Sparsify using multi-rail.

// Control and sync signals
input logic cfg_valid_i, // Used for SVAs only.
input ciph_op_e op_i,
input key_len_e key_len_i,
input logic crypt_i, // Sparsify using multi-rail.
input logic dec_key_gen_i, // Sparsify using multi-rail.
input logic prng_reseed_i,
input logic key_clear_i,
input logic data_out_clear_i,
input logic mux_sel_err_i,
input logic sp_enc_err_i,
input logic rnd_ctr_err_i,
input logic op_err_i,
input logic alert_fatal_i,
output logic alert_o,
input logic cfg_valid_i, // Used for SVAs only.
input ciph_op_e op_i,
input key_len_e key_len_i,
input logic crypt_i, // Sparsify using multi-rail.
input logic dec_key_gen_i, // Sparsify using multi-rail.
input logic prng_reseed_i,
input logic key_clear_i,
input logic data_out_clear_i,
input logic mux_sel_err_i,
input logic sp_enc_err_i,
input logic rnd_ctr_err_i,
input logic op_err_i,
input logic alert_fatal_i,
output logic alert_o,

// Control signals for masking PRNG
output logic prng_update_o,
output logic prng_reseed_req_o,
input logic prng_reseed_ack_i,
output logic prng_update_o,
output logic prng_reseed_req_o,
input logic prng_reseed_ack_i,

// Pseudo-random data input
input logic [WidthPRD-1:0] prd_i,

// Control and sync signals for cipher data path
output state_sel_e state_sel_o,
output logic state_we_o, // Sparsify using multi-rail.
output logic sub_bytes_en_o, // Sparsify using multi-rail.
input logic sub_bytes_out_req_i, // Sparsify using multi-rail.
output logic sub_bytes_out_ack_o, // Sparsify using multi-rail.
output add_rk_sel_e add_rk_sel_o,
output state_sel_e state_sel_o,
output logic state_we_o, // Sparsify using multi-rail.
output logic sub_bytes_en_o, // Sparsify using multi-rail.
input logic sub_bytes_out_req_i, // Sparsify using multi-rail.
output logic sub_bytes_out_ack_o, // Sparsify using multi-rail.
output add_rk_sel_e add_rk_sel_o,

// Control and sync signals for key expand data path
output key_full_sel_e key_full_sel_o,
output logic key_full_we_o, // Sparsify using multi-rail.
output key_dec_sel_e key_dec_sel_o,
output logic key_dec_we_o, // Sparsify using multi-rail.
output logic key_expand_en_o, // Sparsify using multi-rail.
input logic key_expand_out_req_i, // Sparsify using multi-rail.
output logic key_expand_out_ack_o, // Sparsify using multi-rail.
output logic key_expand_clear_o,
output logic [3:0] rnd_ctr_o,
output key_words_sel_e key_words_sel_o,
output round_key_sel_e round_key_sel_o,
output key_full_sel_e key_full_sel_o,
output logic key_full_we_o, // Sparsify using multi-rail.
output key_dec_sel_e key_dec_sel_o,
output logic key_dec_we_o, // Sparsify using multi-rail.
output logic key_expand_en_o, // Sparsify using multi-rail.
input logic key_expand_out_req_i, // Sparsify using multi-rail.
output logic key_expand_out_ack_o, // Sparsify using multi-rail.
output logic key_expand_clear_o,
output logic [3:0] rnd_ctr_o,
output key_words_sel_e key_words_sel_o,
output round_key_sel_e round_key_sel_o,

// Register signals
input logic crypt_q_i, // Sparsify using multi-rail.
output logic crypt_d_o, // Sparsify using multi-rail.
input logic dec_key_gen_q_i, // Sparsify using multi-rail.
output logic dec_key_gen_d_o, // Sparsify using multi-rail.
input logic prng_reseed_q_i,
output logic prng_reseed_d_o,
input logic key_clear_q_i,
output logic key_clear_d_o,
input logic data_out_clear_q_i,
output logic data_out_clear_d_o
input logic crypt_q_i, // Sparsify using multi-rail.
output logic crypt_d_o, // Sparsify using multi-rail.
input logic dec_key_gen_q_i, // Sparsify using multi-rail.
output logic dec_key_gen_d_o, // Sparsify using multi-rail.
input logic prng_reseed_q_i,
output logic prng_reseed_d_o,
input logic key_clear_q_i,
output logic key_clear_d_o,
input logic data_out_clear_q_i,
output logic data_out_clear_d_o
);

// cfg_valid_i is used for SVAs only.
Expand All @@ -94,6 +98,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
logic advance;
logic [2:0] cyc_ctr_d, cyc_ctr_q;
logic cyc_ctr_expr;
logic prng_update;
logic prng_reseed_done_d, prng_reseed_done_q;
logic [3:0] rnd_ctr_d, rnd_ctr_q;
logic [3:0] num_rounds_d, num_rounds_q;
Expand All @@ -110,7 +115,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
out_valid_o = 1'b0;

// Masking PRNG signals
prng_update_o = 1'b0;
prng_update = 1'b0;
prng_reseed_req_o = 1'b0;

// Cipher data path
Expand Down Expand Up @@ -185,7 +190,7 @@ module aes_cipher_control_fsm import aes_pkg::*;

// Make the masking PRNG advance. The current pseudo-random data is used to mask the
// input data.
prng_update_o = SecMasking;
prng_update = SecMasking;

// Init key expand
key_expand_clear_o = 1'b1;
Expand Down Expand Up @@ -236,7 +241,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
// based on key_full_we_o. Request the PRNG update in the first cycle, such that the
// next key_full_we_o pulse will indeed present fresh PRD to the S-Boxes.
advance = key_expand_out_req_i & cyc_ctr_expr;
prng_update_o = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking;
prng_update = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking;
key_expand_en_o = 1'b1;
if (advance) begin
key_expand_out_ack_o = 1'b1;
Expand All @@ -247,7 +252,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
aes_cipher_ctrl_ns = CIPHER_CTRL_ROUND;
end
end else begin
prng_update_o = SecMasking;
prng_update = SecMasking;
state_we_o = ~dec_key_gen_q_i;
rnd_ctr_d = rnd_ctr_q + 4'b0001;
cyc_ctr_d = 3'd0;
Expand Down Expand Up @@ -280,7 +285,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
// such that the next state_we_o / key_full_we_o pulse will indeed present fresh PRD to the
// S-Boxes. Non-DOM S-Boxes need fresh PRD in every clock cycle.
advance = key_expand_out_req_i & cyc_ctr_expr & (dec_key_gen_q_i | sub_bytes_out_req_i);
prng_update_o = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking;
prng_update = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking;
sub_bytes_en_o = ~dec_key_gen_q_i;
key_expand_en_o = 1'b1;

Expand Down Expand Up @@ -363,8 +368,7 @@ module aes_cipher_control_fsm import aes_pkg::*;
// indeed present fresh PRD to the S-Boxes. Update the PRNG only once and in the last cycle
// for non-DOM S-Boxes where otherwise updating the PRNG while being stalled would cause
// the S-Boxes to be re-evaluated, thereby creating additional SCA leakage.
prng_update_o =
(SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : out_valid_o & out_ready_i;
prng_update = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : out_valid_o & out_ready_i;

if (out_valid_o && out_ready_i) begin
sub_bytes_out_ack_o = ~dec_key_gen_q_i;
Expand Down Expand Up @@ -479,6 +483,38 @@ module aes_cipher_control_fsm import aes_pkg::*;
assign cyc_ctr_expr = 1'b1;
end

if (SecSBoxImpl == SBoxImplDom) begin : gen_prd_reg
// The DOM S-Boxes consume fresh PRD only in the first clock cycle and the FSM takes care of
// advancing the masking PRNG accordingly. During the other four clock cycles of every round,
// we randomly advance the masking PRNG to increase noise which is benefitical for SCA
// hardening. These random updates don't propagate across the PRD buffer stage (controlled by
// state_we_o / based on key_expand_en_o) and thus don't lead to partial re-evaluation of the
// S-Boxes which could create undesirable SCA leakage.
logic [WidthPRD-1:0] prd_d, prd_q;

// Reload the shift register whenever the FSM advances the PRNG, e.g., during the first clock
// cycle of every round.
assign prd_d = prng_update ? prd_i : {1'b0, prd_q[WidthPRD-1:1]};
always_ff @(posedge clk_i or negedge rst_ni) begin : reg_prd
if (!rst_ni) begin
prd_q <= '0;
end else begin
prd_q <= prd_d;
end
end

// Advance the masking PRNG based on the FSM and the shift register.
assign prng_update_o = prng_update | prd_q[0];

end else begin : gen_no_prd_reg
// Simply forward the masking PRNG update request for non-DOM S-Boxes.
assign prng_update_o = prng_update;

// Tie off unused inputs.
logic unused_prd;
assign unused_prd = ^prd_i;
end

////////////////
// Assertions //
////////////////
Expand Down
Loading

0 comments on commit 4e738c6

Please sign in to comment.