Skip to content

Commit 1a60ede

Browse files
committed
[kmac] Improve handling of manual PRNG reseeding requests
This commit modifies the design to latch manual PRNG reseeding requests and to indicate the status of the PRNG via new bits in the status register. This allows software to verify that a reseed request has indeed been accepted and prevents the accidental dropping of such requests in case they reach the PRNG while the SHA3 engine is busy. Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
1 parent 5332b70 commit 1a60ede

10 files changed

Lines changed: 159 additions & 31 deletions

File tree

hw/ip/kmac/data/kmac.hjson

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,9 @@
676676
Software can set this bit to 1 to manually trigger the reseeding of the internal PRNG when running in EDN mode.
677677
This will also clear !!ENTROPY_REFRESH_HASH_CNT.
678678

679-
Note that the hardware may miss the trigger pulse if the module is not idle, or if the module is currently performing a reseed operation.
679+
After setting this bit, the !!STATUS.entropy_ready bit should read as 0 and the !!STATUS.entropy_reseeding bit as 1 indicating that a reseed operation is ongoing.
680+
681+
If masking is disabled, this bit is ignored.
680682
'''
681683
}
682684
{ bits: "9"
@@ -715,6 +717,23 @@
715717
In this stage, SW can manually run the hashing engine.
716718
'''
717719
}
720+
{ bits: "4"
721+
name: "entropy_ready"
722+
desc: '''If 1, the internal PRNG is ready.
723+
If 0, the internal PRNG is either not configured in EDN mode or software mode, or currently performing a reseed operation via EDN or waiting for software to provide a new seed.
724+
725+
If masking is disabled, this bit mirrors the !!CFG_SHADOWED.entropy_ready bit.
726+
'''
727+
resval: "0"
728+
}
729+
{ bits: "5"
730+
name: "entropy_reseeding"
731+
desc: '''If 1, the internal PRNG is currently performing a reseed operation via EDN or waiting for software to provide a new seed.
732+
733+
If masking is disabled, this always reads as 0.
734+
'''
735+
resval: "0"
736+
}
718737
{ bits: "12:8"
719738
name: "fifo_depth"
720739
desc: "Count of occupied entries in the message FIFO."

hw/ip/kmac/doc/programmers_guide.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,11 @@ If the value of [`ENTROPY_REFRESH_HASH_CNT`](registers.md#entropy_refresh_hash_c
9494
1. Ensure that the entropy complex is running.
9595
2. Check that the KMAC module is idle by reading the [`STATUS.sha3_idle`](registers.md#status--sha3_idle) bit.
9696
3. Trigger a manual reseed operation by setting the [`CMD.entropy_req`](registers.md#cmd--entropy_req) bit.
97-
4. Configure the module to process a message in cSHAKE mode (but not in KMAC mode).
98-
More precisely, set [`CFG_SHADOWED.mode`](registers.md#cfg_shadowed--mode) to `0x3` and [`CFG_SHADOWED.kmac_en`](registers.md#cfg_shadowed--kmac_en) to 0.
99-
5. Configure the module to use the PRNG and block any hashing operation if the PRNG is not ready by setting [`CFG_SHADOWED.entropy_fast_process`](registers.md#cfg_shadowed--entropy_fast_process) to 0.
100-
6. Send the `start` command to the [`CMD`](registers.md#cmd) register.
101-
The SHA3 engine will start loading and hashing the function name `N` and the customization string `S` first.
102-
7. Send the `process` command to the [`CMD`](registers.md#cmd) register.
103-
8. Wait for the [`STATUS.sha3_squeeze`](registers.md#status--sha3_squeeze) bit to get set.
104-
Due to the ongoing reseed operation, the [`STATUS.sha3_squeeze`](registers.md#status--sha3_squeeze) bit should remain 0 for an extended period of time.
105-
9. Send the `done` command to the [`CMD`](registers.md#cmd) register to finish processing.
97+
4. Wait for the [`STATUS.entropy_reseeding`](registers.md#status--entropy_reseeding) bit to get set.
98+
Due to the ongoing reseed operation, the [`STATUS.entropy_reseeding`](registers.md#status--entropy_reseeding) bit should remain 1 for an extended period of time.
99+
5. Wait for the [`STATUS.entropy_reseeding`](registers.md#status--entropy_reseeding) bit to get cleared and the [`STATUS.entropy_ready`](registers.md#status--entropy_ready) bit to get set.
106100

107101
The [`ENTROPY_REFRESH_HASH_CNT`](registers.md#entropy_refresh_hash_cnt) register should now read as 0.
108-
Note however that if the manual reseed operation is triggered while the KMAC module is busy, the reseed operation may get skipped despite the hash counter being cleared back to 0.
109102

110103

111104
#### Checking Message FIFO depth before pushing data

hw/ip/kmac/doc/registers.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ Software can set this bit to 1 to manually clear [`ENTROPY_REFRESH_HASH_CNT.`](#
369369
Software can set this bit to 1 to manually trigger the reseeding of the internal PRNG when running in EDN mode.
370370
This will also clear [`ENTROPY_REFRESH_HASH_CNT.`](#entropy_refresh_hash_cnt)
371371

372-
Note that the hardware may miss the trigger pulse if the module is not idle, or if the module is currently performing a reseed operation.
372+
After setting this bit, the [`STATUS.entropy_ready`](#status) bit should read as 0 and the [`STATUS.entropy_reseeding`](#status) bit as 1 indicating that a reseed operation is ongoing.
373+
374+
If masking is disabled, this bit is ignored.
373375

374376
### CMD . cmd
375377
Issue a command to the KMAC/SHA3 IP. The command is sparse
@@ -389,12 +391,12 @@ Other values are reserved.
389391
KMAC/SHA3 Status register.
390392
- Offset: `0x1c`
391393
- Reset default: `0x4001`
392-
- Reset mask: `0x3df07`
394+
- Reset mask: `0x3df37`
393395

394396
### Fields
395397

396398
```wavejson
397-
{"reg": [{"name": "sha3_idle", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "sha3_absorb", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "sha3_squeeze", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 5}, {"name": "fifo_depth", "bits": 5, "attr": ["ro"], "rotate": -90}, {"bits": 1}, {"name": "fifo_empty", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "fifo_full", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ALERT_FATAL_FAULT", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ALERT_RECOV_CTRL_UPDATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 14}], "config": {"lanes": 1, "fontsize": 10, "vspace": 290}}
399+
{"reg": [{"name": "sha3_idle", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "sha3_absorb", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "sha3_squeeze", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 1}, {"name": "entropy_ready", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "entropy_reseeding", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 2}, {"name": "fifo_depth", "bits": 5, "attr": ["ro"], "rotate": -90}, {"bits": 1}, {"name": "fifo_empty", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "fifo_full", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ALERT_FATAL_FAULT", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ALERT_RECOV_CTRL_UPDATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 14}], "config": {"lanes": 1, "fontsize": 10, "vspace": 290}}
398400
```
399401

400402
| Bits | Type | Reset | Name |
@@ -406,7 +408,10 @@ KMAC/SHA3 Status register.
406408
| 14 | ro | 0x1 | [fifo_empty](#status--fifo_empty) |
407409
| 13 | | | Reserved |
408410
| 12:8 | ro | x | [fifo_depth](#status--fifo_depth) |
409-
| 7:3 | | | Reserved |
411+
| 7:6 | | | Reserved |
412+
| 5 | ro | 0x0 | [entropy_reseeding](#status--entropy_reseeding) |
413+
| 4 | ro | 0x0 | [entropy_ready](#status--entropy_ready) |
414+
| 3 | | | Reserved |
410415
| 2 | ro | x | [sha3_squeeze](#status--sha3_squeeze) |
411416
| 1 | ro | x | [sha3_absorb](#status--sha3_absorb) |
412417
| 0 | ro | 0x1 | [sha3_idle](#status--sha3_idle) |
@@ -444,6 +449,17 @@ See the "Message FIFO" section in the spec for the reason.
444449
### STATUS . fifo_depth
445450
Count of occupied entries in the message FIFO.
446451

452+
### STATUS . entropy_reseeding
453+
If 1, the internal PRNG is currently performing a reseed operation via EDN or waiting for software to provide a new seed.
454+
455+
If masking is disabled, this always reads as 0.
456+
457+
### STATUS . entropy_ready
458+
If 1, the internal PRNG is ready.
459+
If 0, the internal PRNG is either not configured in EDN mode or software mode, or currently performing a reseed operation via EDN or waiting for software to provide a new seed.
460+
461+
If masking is disabled, this bit mirrors the [`CFG_SHADOWED.entropy_ready`](#cfg_shadowed) bit.
462+
447463
### STATUS . sha3_squeeze
448464
If 1, SHA3 completes sponge absorbing stage.
449465
In this stage, SW can manually run the hashing engine.

hw/ip/kmac/dv/env/kmac_env_pkg.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ package kmac_env_pkg;
123123
KmacStatusSha3Idle = 0,
124124
KmacStatusSha3Absorb = 1,
125125
KmacStatusSha3Squeeze = 2,
126+
KmacStatusEntropyReady = 4,
127+
KmacStatusEntropyReseeding = 5,
126128
KmacStatusFifoDepthLSB = 8,
127129
KmacStatusFifoDepthMSB = 12,
128130
KmacStatusFifoEmpty = 14,

hw/ip/kmac/dv/env/kmac_scoreboard.sv

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ class kmac_scoreboard extends cip_base_scoreboard #(.CFG_T(kmac_env_cfg),
7979
bit sha3_absorb;
8080
bit sha3_squeeze;
8181

82+
// PRNG status bits
83+
bit status_entropy_ready;
84+
bit status_entropy_reseeding;
85+
8286
// FIFO status bits
8387
bit cmd_process_triggered;
8488
bit msgfifo_access;
@@ -966,6 +970,8 @@ class kmac_scoreboard extends cip_base_scoreboard #(.CFG_T(kmac_env_cfg),
966970
exp_status[KmacStatusSha3Absorb] = sha3_absorb;
967971
exp_status[KmacStatusSha3Squeeze] = sha3_squeeze;
968972

973+
exp_status[KmacStatusEntropyReady] = status_entropy_ready;
974+
exp_status[KmacStatusEntropyReseeding] = status_entropy_reseeding;
969975

970976
void'(ral.status.predict(.value(exp_status), .kind(UVM_PREDICT_READ)));
971977

@@ -1837,9 +1843,15 @@ class kmac_scoreboard extends cip_base_scoreboard #(.CFG_T(kmac_env_cfg),
18371843

18381844
function void set_entropy_fetch(bit val);
18391845
if (val) begin
1840-
if (entropy_mode == EntropyModeEdn) in_edn_fetch = cfg.enable_masking;
1846+
if (entropy_mode == EntropyModeEdn) begin
1847+
in_edn_fetch = cfg.enable_masking;
1848+
status_entropy_reseeding = cfg.enable_masking;
1849+
status_entropy_ready = cfg.enable_masking ? 0 : entropy_ready;
1850+
end
18411851
end else begin
18421852
in_edn_fetch = 0;
1853+
status_entropy_reseeding = 0;
1854+
status_entropy_ready = 1;
18431855
`uvm_info(`gfn, "dropped in_edn_fetch", UVM_HIGH)
18441856
end
18451857
endfunction

hw/ip/kmac/rtl/kmac.sv

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ module kmac
306306

307307
prim_mubi_pkg::mubi4_t entropy_configured;
308308

309+
logic status_entropy_ready;
310+
logic status_entropy_reseeding;
311+
309312
// Message Masking
310313
logic msg_mask_en, cfg_msg_mask;
311314
logic [MsgWidth-1:0] msg_mask;
@@ -465,6 +468,9 @@ module kmac
465468
assign hw2reg.status.sha3_absorb.d = sha3_fsm == sha3_pkg::StAbsorb;
466469
assign hw2reg.status.sha3_squeeze.d = sha3_fsm == sha3_pkg::StSqueeze;
467470

471+
assign hw2reg.status.entropy_ready.d = status_entropy_ready;
472+
assign hw2reg.status.entropy_reseeding.d = status_entropy_reseeding;
473+
468474
// FIFO related status
469475
assign hw2reg.status.fifo_depth.d[MsgFifoDepthW-1:0] = msgfifo_depth;
470476
if ($bits(hw2reg.status.fifo_depth.d) != MsgFifoDepthW) begin : gen_fifo_depth_tie
@@ -1308,6 +1314,8 @@ module kmac
13081314
.hash_threshold_i (entropy_hash_threshold),
13091315

13101316
.entropy_configured_o (entropy_configured),
1317+
.entropy_ready_o (status_entropy_ready),
1318+
.entropy_reseeding_o (status_entropy_reseeding),
13111319

13121320
// LC escalation
13131321
.lc_escalate_en_i (lc_escalate_en[5]),
@@ -1363,6 +1371,12 @@ module kmac
13631371
// If Masking is off, always entropy configured
13641372
assign entropy_configured = prim_mubi_pkg::MuBi4True;
13651373

1374+
// Mirror the entropy_ready bit written by software to simplify DV and software.
1375+
assign status_entropy_ready = reg2hw.cfg_shadowed.entropy_ready.q;
1376+
1377+
// No reseed operation is ever happening.
1378+
assign status_entropy_reseeding = 1'b 0;
1379+
13661380
logic unused_edn_clk_rst;
13671381
assign unused_edn_clk_rst = ^{clk_edn_i, rst_edn_ni};
13681382

hw/ip/kmac/rtl/kmac_entropy.sv

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ module kmac_entropy
7070
input [HashCntW-1:0] hash_threshold_i,
7171

7272
output prim_mubi_pkg::mubi4_t entropy_configured_o,
73+
output logic entropy_ready_o,
74+
output logic entropy_reseeding_o,
7375

7476
// Life cycle
7577
input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
@@ -297,7 +299,6 @@ module kmac_entropy
297299

298300
// Hash Counter
299301
logic threshold_hit;
300-
logic threshold_hit_q, threshold_hit_clr; // latched hit
301302

302303
logic hash_progress_d, hash_progress_q;
303304
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -337,15 +338,29 @@ module kmac_entropy
337338
assign threshold_hit = |hash_threshold_i && (hash_threshold_i <= hash_cnt_o);
338339

339340
always_ff @(posedge clk_i or negedge rst_ni) begin
340-
if (!rst_ni) threshold_hit_q <= 1'b 0;
341-
else if (threshold_hit_clr) threshold_hit_q <= 1'b 0;
342-
else if (threshold_hit) threshold_hit_q <= 1'b 1;
341+
if (!rst_ni) mode_q <= EntropyModeNone;
342+
else if (mode_latch) mode_q <= mode_i;
343343
end
344344

345+
// EDN reseed triggering ====================================================
346+
logic edn_trigger_clr;
347+
logic edn_trigger_d, edn_trigger_q;
348+
349+
// The entropy_refresh_req_i input from software and the threshold_hit signal
350+
// are both pulses. Latch them.
351+
assign edn_trigger_d =
352+
((mode_q == EntropyModeEdn) &&
353+
(entropy_refresh_req_i || threshold_hit)) ? 1'b1 :
354+
edn_trigger_clr ? 1'b0 : edn_trigger_q;
355+
345356
always_ff @(posedge clk_i or negedge rst_ni) begin
346-
if (!rst_ni) mode_q <= EntropyModeNone;
347-
else if (mode_latch) mode_q <= mode_i;
357+
if (!rst_ni) begin
358+
edn_trigger_q <= 1'b0;
359+
end else begin
360+
edn_trigger_q <= edn_trigger_d;
361+
end
348362
end
363+
// EDN reseed triggering ----------------------------------------------------
349364

350365
// PRNG primitive ===========================================================
351366

@@ -497,7 +512,7 @@ module kmac_entropy
497512
timer_enable = 1'b 0;
498513
timer_update = 1'b 0;
499514

500-
threshold_hit_clr = 1'b 0;
515+
edn_trigger_clr = 1'b 0;
501516

502517
// rand is valid when this logic expands the entropy.
503518
// FSM sets the valid signal, the signal is cleared by `consume` signal
@@ -521,6 +536,10 @@ module kmac_entropy
521536
data_update = 1'b 0;
522537
aux_update = 1'b 0;
523538

539+
// Status
540+
entropy_ready_o = 1'b 0;
541+
entropy_reseeding_o = 1'b 0;
542+
524543
// Error
525544
err_o = '{valid: 1'b 0, code: ErrNone, info: '0};
526545

@@ -570,6 +589,8 @@ module kmac_entropy
570589

571590
prng_en = prng_en_rand_q[0];
572591

592+
entropy_ready_o = 1'b 1;
593+
573594
if ((rand_update_i || rand_consumed_i) &&
574595
((fast_process_i && in_keyblock_i) || !fast_process_i)) begin
575596
// If fast_process is set, don't clear the rand valid, even
@@ -586,17 +607,13 @@ module kmac_entropy
586607
end else begin
587608
st_d = StRandReady;
588609
end
589-
end else if ((mode_q == EntropyModeEdn) &&
590-
(entropy_refresh_req_i || threshold_hit_q)) begin
610+
end else if (edn_trigger_q) begin
591611
// Start reseeding the PRNG via EDN.
592612
seed_en = 1'b 1;
593613
st_d = StRandEdn;
594614

595615
// Timer reset
596616
timer_update = 1'b 1;
597-
598-
// Clear the threshold as it refreshes the hash
599-
threshold_hit_clr = 1'b 1;
600617
end else begin
601618
st_d = StRandReady;
602619
end
@@ -609,6 +626,9 @@ module kmac_entropy
609626
// Wait timer
610627
timer_enable = 1'b 1;
611628

629+
// Status
630+
entropy_reseeding_o = 1'b 1;
631+
612632
if (timer_expired && non_zero_wait_timer_limit) begin
613633
// If timer count is non-zero and expired;
614634
st_d = StRandErrWaitExpired;
@@ -617,6 +637,7 @@ module kmac_entropy
617637
seed_ack = 1'b 1;
618638

619639
if (seed_done) begin
640+
edn_trigger_clr = 1'b 1;
620641
st_d = StRandGenerate;
621642

622643
if ((fast_process_i && in_keyblock_i) || !fast_process_i) begin
@@ -648,6 +669,9 @@ module kmac_entropy
648669
// Forward ack driven by software.
649670
seed_ack = seed_req & seed_update_i;
650671

672+
// Status
673+
entropy_reseeding_o = 1'b 1;
674+
651675
if (seed_done) begin
652676
st_d = StRandGenerate;
653677

@@ -678,6 +702,8 @@ module kmac_entropy
678702
rand_valid_set = 1'b 1;
679703
prng_en = prng_en_rand_q[0];
680704

705+
entropy_ready_o = 1'b 1;
706+
681707
st_d = StRandReady;
682708
end
683709

hw/ip/kmac/rtl/kmac_reduced.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ module kmac_reduced
8282

8383
// Entropy status signals
8484
output prim_mubi_pkg::mubi4_t entropy_configured_o,
85+
output logic entropy_ready_o,
86+
output logic entropy_reseeding_o,
8587
input logic [HashCntW-1:0] entropy_hash_threshold_i, // drive to max
8688
input logic entropy_hash_clr_i, // drive to 0
8789
output logic [HashCntW-1:0] entropy_hash_cnt_o,
@@ -298,6 +300,8 @@ module kmac_reduced
298300
.hash_cnt_o (entropy_hash_cnt_o),
299301

300302
.entropy_configured_o(entropy_configured_o),
303+
.entropy_ready_o (entropy_ready_o),
304+
.entropy_reseeding_o (entropy_reseeding_o),
301305

302306
// LC escalation
303307
.lc_escalate_en_i(lc_escalate_en[1]),

hw/ip/kmac/rtl/kmac_reg_pkg.sv

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ package kmac_reg_pkg;
218218
struct packed {
219219
logic [4:0] d;
220220
} fifo_depth;
221+
struct packed {
222+
logic d;
223+
} entropy_reseeding;
224+
struct packed {
225+
logic d;
226+
} entropy_ready;
221227
struct packed {
222228
logic d;
223229
} sha3_squeeze;
@@ -259,9 +265,9 @@ package kmac_reg_pkg;
259265

260266
// HW -> register type
261267
typedef struct packed {
262-
kmac_hw2reg_intr_state_reg_t intr_state; // [62:57]
263-
kmac_hw2reg_cfg_regwen_reg_t cfg_regwen; // [56:56]
264-
kmac_hw2reg_status_reg_t status; // [55:44]
268+
kmac_hw2reg_intr_state_reg_t intr_state; // [64:59]
269+
kmac_hw2reg_cfg_regwen_reg_t cfg_regwen; // [58:58]
270+
kmac_hw2reg_status_reg_t status; // [57:44]
265271
kmac_hw2reg_entropy_refresh_hash_cnt_reg_t entropy_refresh_hash_cnt; // [43:33]
266272
kmac_hw2reg_err_code_reg_t err_code; // [32:0]
267273
} kmac_hw2reg_t;
@@ -338,6 +344,8 @@ package kmac_reg_pkg;
338344
parameter logic [10:0] KMAC_CMD_RESVAL = 11'h 0;
339345
parameter logic [17:0] KMAC_STATUS_RESVAL = 18'h 4001;
340346
parameter logic [0:0] KMAC_STATUS_SHA3_IDLE_RESVAL = 1'h 1;
347+
parameter logic [0:0] KMAC_STATUS_ENTROPY_READY_RESVAL = 1'h 0;
348+
parameter logic [0:0] KMAC_STATUS_ENTROPY_RESEEDING_RESVAL = 1'h 0;
341349
parameter logic [0:0] KMAC_STATUS_FIFO_EMPTY_RESVAL = 1'h 1;
342350
parameter logic [0:0] KMAC_STATUS_ALERT_FATAL_FAULT_RESVAL = 1'h 0;
343351
parameter logic [0:0] KMAC_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_RESVAL = 1'h 0;

0 commit comments

Comments
 (0)