[kmac] fit: Message Masking
What does this commit?
This commit implements the message masking when a config bit is set.
Why is this beneficial?
By masking the message, the 1600bit (2share) storage becomes more
randomized by PRNG. It alleviates the distinct moment of the
prefix/key/message data shift moments. In the previous design, the
prefix, key are padded by 0. But as those blocks are XORed with PRNG
before fed into the SHA3 module, it is more randomized.
In contrast, with this config bit, the operation consumes more power as
LFSR runs when the message is fed into the hashing module.
Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/kmac/data/kmac.hjson b/hw/ip/kmac/data/kmac.hjson
index 6f47285..7217492 100644
--- a/hw/ip/kmac/data/kmac.hjson
+++ b/hw/ip/kmac/data/kmac.hjson
@@ -114,6 +114,12 @@
randcount: "64",
randtype: "perm",
}
+ { name: "RndCnstMsgPerm"
+ desc: "Compile-time random permutation for LFSR Message output"
+ type: "kmac_pkg::msg_perm_t"
+ randcount: "64"
+ randtype: "perm"
+ }
]
inter_signal_list: [
{ struct: "hw_key_req"
@@ -371,6 +377,14 @@
'''
tags: ["shadowed_reg_path:u_cfg_reg_shadowed.u_cfg_reg_shadowed_entropy_fast_process"]
} // f: entropy_fast_process
+ { bits: "20"
+ name: msg_mask
+ desc: '''Message Masking with PRNG.
+
+ If 1, KMAC applies PRNG to the input messages to the Keccak module
+ when KMAC mode is on.
+ '''
+ } // f: msg_mask
{ bits: "24"
name: entropy_ready
desc: '''Entropy Ready status.
diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv
index 5ea0d51..1db6402 100644
--- a/hw/ip/kmac/rtl/kmac.sv
+++ b/hw/ip/kmac/rtl/kmac.sv
@@ -30,6 +30,7 @@
parameter bit SecIdleAcceptSwMsg = 1'b0,
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
+ parameter msg_perm_t RndCnstMsgPerm = RndCnstMsgPermDefault,
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}
) (
@@ -232,6 +233,7 @@
// KMAC to SHA3 core
logic msg_valid ;
logic [kmac_pkg::MsgWidth-1:0] msg_data [Share];
+ logic [kmac_pkg::MsgWidth-1:0] msg_data_masked [Share];
logic [kmac_pkg::MsgStrbW-1:0] msg_strb ;
logic msg_ready ;
@@ -283,6 +285,10 @@
entropy_mode_e entropy_mode;
logic entropy_fast_process;
+ // Message Masking
+ logic msg_mask_en, cfg_msg_mask;
+ logic [MsgWidth-1:0] msg_mask;
+
// SHA3 Error response
sha3_pkg::err_t sha3_err;
@@ -506,6 +512,10 @@
assign entropy_mode = entropy_mode_e'(reg2hw.cfg_shadowed.entropy_mode.q);
assign entropy_fast_process = reg2hw.cfg_shadowed.entropy_fast_process.q;
+ // msg_mask_en turns on the message LFSR when KMAC is enabled.
+ assign cfg_msg_mask = reg2hw.cfg_shadowed.msg_mask.q;
+ assign msg_mask_en = cfg_msg_mask & msg_valid & msg_ready;
+
`ASSERT(EntropyReadyLatched_A, $rose(entropy_ready) |=> !entropy_ready)
// Idle control (registered output)
@@ -797,6 +807,30 @@
);
// SHA3 hashing engine
+
+ // msg_data masking
+ if (EnMasking == 1) begin: g_msg_mask
+ logic [MsgWidth-1:0] msg_mask_permuted;
+
+ // Permute the LFSR output to avoid same lfsr applied to multiple times
+ always_comb begin
+ msg_mask_permuted = '0;
+ for (int unsigned i = 0 ; i < MsgWidth ; i++) begin
+ // Loop through the MsgPerm constant and swap between the bits
+ msg_mask_permuted[i] = msg_mask[RndCnstMsgPerm[i]];
+ end
+ end
+
+ for (genvar i = 0 ; i < Share ; i++) begin: g_msg_mask
+ assign msg_data_masked[i] = msg_data[i]
+ ^ ({MsgWidth{cfg_msg_mask}} & msg_mask_permuted);
+ end : g_msg_mask
+ end else begin : g_no_msg_mask
+ assign msg_data_masked[0] = msg_data[0];
+
+ logic unused_msgmask;
+ assign unused_msgmask = ^{msg_mask, cfg_msg_mask, msg_mask_en};
+ end
sha3 #(
.EnMasking (EnMasking),
.ReuseShare (ReuseShare)
@@ -806,7 +840,7 @@
// MSG_FIFO interface (or from KMAC)
.msg_valid_i (msg_valid),
- .msg_data_i (msg_data ), // always store to 0 regardless of EnMasking
+ .msg_data_i (msg_data_masked ),
.msg_strb_i (msg_strb ),
.msg_ready_o (msg_ready),
@@ -1112,6 +1146,10 @@
.wait_timer_prescaler_i (wait_timer_prescaler),
.wait_timer_limit_i (wait_timer_limit),
+ //// Message Masking
+ .msg_mask_en_i (msg_mask_en),
+ .lfsr_data_o (msg_mask),
+
//// SW update of seed
.seed_update_i (entropy_seed_update),
.seed_data_i (entropy_seed_data),
@@ -1203,6 +1241,7 @@
reg2hw.cfg_shadowed.sideload.err_storage ,
reg2hw.cfg_shadowed.entropy_mode.err_storage ,
reg2hw.cfg_shadowed.entropy_fast_process.err_storage,
+ reg2hw.cfg_shadowed.msg_mask.err_storage ,
reg2hw.cfg_shadowed.entropy_ready.err_storage ,
reg2hw.cfg_shadowed.err_processed.err_storage
};
@@ -1216,6 +1255,7 @@
reg2hw.cfg_shadowed.sideload.err_update ,
reg2hw.cfg_shadowed.entropy_mode.err_update ,
reg2hw.cfg_shadowed.entropy_fast_process.err_update ,
+ reg2hw.cfg_shadowed.msg_mask.err_update ,
reg2hw.cfg_shadowed.entropy_ready.err_update ,
reg2hw.cfg_shadowed.err_processed.err_update
};
@@ -1229,7 +1269,8 @@
reg2hw.cfg_shadowed.state_endianness.qe ,
reg2hw.cfg_shadowed.sideload.qe ,
reg2hw.cfg_shadowed.entropy_mode.qe ,
- reg2hw.cfg_shadowed.entropy_fast_process.qe
+ reg2hw.cfg_shadowed.entropy_fast_process.qe ,
+ reg2hw.cfg_shadowed.msg_mask.qe
};
// Alerts
diff --git a/hw/ip/kmac/rtl/kmac_entropy.sv b/hw/ip/kmac/rtl/kmac_entropy.sv
index 4b57af5..22ae82a 100644
--- a/hw/ip/kmac/rtl/kmac_entropy.sv
+++ b/hw/ip/kmac/rtl/kmac_entropy.sv
@@ -37,6 +37,11 @@
//// rand_valid_o unless it is not processing KeyBlock.
input fast_process_i,
+ //// LFSR Enable for Message Masking
+ //// If 1, LFSR advances to create 64-bit PRNG. This input is used to mask the message fed into SHA3 (Keccak).
+ input msg_mask_en_i,
+ output logic [MsgWidth-1:0] lfsr_data_o,
+
//// SW update of seed
input seed_update_i,
input [63:0] seed_data_i,
@@ -320,11 +325,13 @@
.rst_ni,
.seed_en_i(lfsr_seed_en),
.seed_i (lfsr_seed),
- .lfsr_en_i(lfsr_en),
+ .lfsr_en_i(lfsr_en || msg_mask_en_i ),
.entropy_i('0), // Does not use additional entropy while operating
.state_o (lfsr_data), // (partial) LFSR state output StateOutDw
.err_o (lfsr_error_o)
);
+ assign lfsr_data_o = lfsr_data; // For masking the message
+
// LFSR ---------------------------------------------------------------------
// 320-bit storage ==========================================================
diff --git a/hw/ip/kmac/rtl/kmac_pkg.sv b/hw/ip/kmac/rtl/kmac_pkg.sv
index 93a1ed8..669c2b3 100644
--- a/hw/ip/kmac/rtl/kmac_pkg.sv
+++ b/hw/ip/kmac/rtl/kmac_pkg.sv
@@ -98,6 +98,15 @@
256'h970d171aa41948cbe3a58167d3b47c268acfcbb2fa627b9c0a2fdf578f4ed32b
};
+ // These LFSR parameters have been generated with
+ // $ ./util/design/gen-lfsr-seed.py --width 64 --seed 1201202158 --prefix ""
+ // And changed the type name from lfsr_perm_t to msg_perm_t
+ typedef logic [EntropyLfsrW-1:0][$clog2(EntropyLfsrW)-1:0] msg_perm_t;
+ parameter msg_perm_t RndCnstMsgPermDefault = {
+ 128'h382af41849db4cfb9c885f72f118c102,
+ 256'hcb5526978defac799192f65f54148379af21d7e10d82a5a33c3f31a1eaf964b8
+ };
+
///////////////////////////
// Application interface //
///////////////////////////
diff --git a/hw/ip/kmac/rtl/kmac_reg_pkg.sv b/hw/ip/kmac/rtl/kmac_reg_pkg.sv
index 0edbcf7..0765a20 100644
--- a/hw/ip/kmac/rtl/kmac_reg_pkg.sv
+++ b/hw/ip/kmac/rtl/kmac_reg_pkg.sv
@@ -123,6 +123,12 @@
logic qe;
logic err_update;
logic err_storage;
+ } msg_mask;
+ struct packed {
+ logic q;
+ logic qe;
+ logic err_update;
+ logic err_storage;
} entropy_ready;
struct packed {
logic q;
@@ -250,11 +256,11 @@
// Register -> HW type
typedef struct packed {
- kmac_reg2hw_intr_state_reg_t intr_state; // [1561:1559]
- kmac_reg2hw_intr_enable_reg_t intr_enable; // [1558:1556]
- kmac_reg2hw_intr_test_reg_t intr_test; // [1555:1550]
- kmac_reg2hw_alert_test_reg_t alert_test; // [1549:1546]
- kmac_reg2hw_cfg_shadowed_reg_t cfg_shadowed; // [1545:1522]
+ kmac_reg2hw_intr_state_reg_t intr_state; // [1563:1561]
+ kmac_reg2hw_intr_enable_reg_t intr_enable; // [1560:1558]
+ kmac_reg2hw_intr_test_reg_t intr_test; // [1557:1552]
+ kmac_reg2hw_alert_test_reg_t alert_test; // [1551:1548]
+ kmac_reg2hw_cfg_shadowed_reg_t cfg_shadowed; // [1547:1522]
kmac_reg2hw_cmd_reg_t cmd; // [1521:1513]
kmac_reg2hw_entropy_period_reg_t entropy_period; // [1512:1487]
kmac_reg2hw_entropy_refresh_reg_t entropy_refresh; // [1486:1477]
diff --git a/hw/ip/kmac/rtl/kmac_reg_top.sv b/hw/ip/kmac/rtl/kmac_reg_top.sv
index b61266d..d3e0619 100644
--- a/hw/ip/kmac/rtl/kmac_reg_top.sv
+++ b/hw/ip/kmac/rtl/kmac_reg_top.sv
@@ -209,6 +209,8 @@
logic [1:0] cfg_shadowed_entropy_mode_wd;
logic cfg_shadowed_entropy_fast_process_qs;
logic cfg_shadowed_entropy_fast_process_wd;
+ logic cfg_shadowed_msg_mask_qs;
+ logic cfg_shadowed_msg_mask_wd;
logic cfg_shadowed_entropy_ready_qs;
logic cfg_shadowed_entropy_ready_wd;
logic cfg_shadowed_err_processed_qs;
@@ -859,6 +861,40 @@
.err_storage (reg2hw.cfg_shadowed.entropy_fast_process.err_storage)
);
+ // F[msg_mask]: 20:20
+ prim_subreg_shadow #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRW),
+ .RESVAL (1'h0)
+ ) u_cfg_shadowed_msg_mask (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .rst_shadowed_ni (rst_shadowed_ni),
+
+ // from register interface
+ .re (cfg_shadowed_re),
+ .we (cfg_shadowed_we & cfg_regwen_qs),
+ .wd (cfg_shadowed_msg_mask_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0),
+
+ // to internal hardware
+ .qe (reg2hw.cfg_shadowed.msg_mask.qe),
+ .q (reg2hw.cfg_shadowed.msg_mask.q),
+
+ // to register interface (read)
+ .qs (cfg_shadowed_msg_mask_qs),
+
+ // Shadow register phase. Relevant for hwext only.
+ .phase (),
+
+ // Shadow register error conditions
+ .err_update (reg2hw.cfg_shadowed.msg_mask.err_update),
+ .err_storage (reg2hw.cfg_shadowed.msg_mask.err_storage)
+ );
+
// F[entropy_ready]: 24:24
prim_subreg_shadow #(
.DW (1),
@@ -2275,6 +2311,8 @@
assign cfg_shadowed_entropy_fast_process_wd = reg_wdata[19];
+ assign cfg_shadowed_msg_mask_wd = reg_wdata[20];
+
assign cfg_shadowed_entropy_ready_wd = reg_wdata[24];
assign cfg_shadowed_err_processed_wd = reg_wdata[25];
@@ -2473,6 +2511,7 @@
reg_rdata_next[12] = cfg_shadowed_sideload_qs;
reg_rdata_next[17:16] = cfg_shadowed_entropy_mode_qs;
reg_rdata_next[19] = cfg_shadowed_entropy_fast_process_qs;
+ reg_rdata_next[20] = cfg_shadowed_msg_mask_qs;
reg_rdata_next[24] = cfg_shadowed_entropy_ready_qs;
reg_rdata_next[25] = cfg_shadowed_err_processed_qs;
end