Skip to content

Commit

Permalink
[hmac,dv] Scoreboard checks for different digest sizes
Browse files Browse the repository at this point in the history
This updates the scoreboard for checks for different digest
sizes and key lengths, in normal operation and in secure
wiping.

Signed-off-by: Ghada Dessouky <[email protected]>
  • Loading branch information
gdessouky committed May 14, 2024
1 parent b090c13 commit 58ec412
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 44 deletions.
90 changes: 57 additions & 33 deletions hw/ip/hmac/dv/env/hmac_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class hmac_scoreboard extends cip_base_scoreboard #(.CFG_T (hmac_env_cfg),
previous_digest_swap = ral.cfg.digest_swap.get_mirrored_value();

`uvm_info(`gfn, $sformatf(
"Setting previous digest and digest swap: %4b",
"setting previous digest and digest swap: %4b",
previous_digest_size), UVM_HIGH)
end
end
Expand Down Expand Up @@ -268,31 +268,19 @@ class hmac_scoreboard extends cip_base_scoreboard #(.CFG_T (hmac_env_cfg),
// Read and check DIGEST while HMAC is enabled/disabled
if (cfg.en_cov) cov.rd_digest_during_hmac_en_cg.sample(`gmv(ral.cfg.hmac_en));

// TODO: will need this chunk of code if we decide to hold the previous digest
// value after HMAC is configured with new size etc. when doing DV for
// the new digest sizes

/* if (previous_digest_swap != ral.cfg.digest_swap.get_mirrored_value()) begin
expected_digest_swap = previous_digest_swap;
end else begin
expected_digest_swap = ral.cfg.digest_swap.get_mirrored_value();
end */

// when testing only 256-bit now, digest output is wired directly
// to registers and swaps are directly reflected in the CSRs
// so do not need to hold previous digest swap cfg
expected_digest_swap = ral.cfg.digest_swap.get_mirrored_value();

if (expected_digest_swap == 1'b0) begin
// this only swaps the 32-bit word, but not the full 64-bit digest word for the
// extended modes, have to swap checks at the bottom
// extended digest sizes, have to swap checks at the bottom
real_digest_val = {<<8{item.d_data}};
end else begin
real_digest_val = item.d_data;
end

// decide whether to assume previous or new digest size to compare correctly
// with the expected digest
// with the expected digest, because digests are retained from previous operation
// until new configuration is successfully started
if (previous_digest_size != ral.cfg.digest_size.get_mirrored_value()) begin
expected_digest_size = previous_digest_size;
end else begin
Expand All @@ -304,47 +292,83 @@ class hmac_scoreboard extends cip_base_scoreboard #(.CFG_T (hmac_env_cfg),
previous_digest_size, ral.cfg.digest_size.get_mirrored_value(),
expected_digest_size), UVM_HIGH)

// If wipe_secret is triggered, ensure the predicted value does not match the readout
// digest.
// If wipe_secret is triggered, ensure the predicted value does not match the read out
// digest and update the predicted value with the read out value.
if (cfg.wipe_secret_triggered) begin
if (expected_digest_size == SHA2_256) begin
if (digest_idx < 8) begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx]);
`uvm_info(`gfn, $sformatf("Updating digest to read value after wiping 0x%0h",
exp_digest[digest_idx]), UVM_LOW)
// Update new digest data to the exp_digest variable.
exp_digest[digest_idx] = real_digest_val;
end else if (expected_digest_size == SHA2_384) begin
if (expected_digest_swap == 1'b0) begin
if (digest_idx % 2) begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx-1]);
// Update new digest data to the exp_digest variable.
` uvm_info(`gfn, $sformatf("Updating digest to read value after wiping 0x%0h",
exp_digest[digest_idx-1]), UVM_LOW)
exp_digest[digest_idx-1] = real_digest_val;
end else begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx+1]);
// Update new digest data to the exp_digest variable.
`uvm_info(`gfn, $sformatf("Updating digest to read value after wiping 0x%0h",
exp_digest[digest_idx+1]), UVM_LOW)
exp_digest[digest_idx+1] = real_digest_val;
end
end else begin
` DV_CHECK_NE(real_digest_val, exp_digest[digest_idx]);
// Update new digest data to the exp_digest variable.
`uvm_info(`gfn, $sformatf("Updating digest to read value after wiping 0x%0h",
exp_digest[digest_idx]), UVM_LOW)
exp_digest[digest_idx] = real_digest_val;
end
end else if (expected_digest_size == SHA2_512) begin
if (expected_digest_swap == 1'b0) begin
if (digest_idx % 2) begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx-1]);
exp_digest[digest_idx-1] = real_digest_val;
end else begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx+1]);
exp_digest[digest_idx+1] = real_digest_val;
end
end else begin
`DV_CHECK_NE(real_digest_val, exp_digest[digest_idx]);
// Update new digest data to the exp_digest variable.
exp_digest[digest_idx] = real_digest_val;
`uvm_info(`gfn, $sformatf("Updating digest to read value after wiping 0x%0h",
exp_digest[digest_idx]), UVM_HIGH)
exp_digest[digest_idx]), UVM_LOW)
exp_digest[digest_idx] = real_digest_val;
end
end
end else begin
`uvm_info(`gfn, $sformatf("expected digest[%0d] 0x%0h",
digest_idx, exp_digest[digest_idx]), UVM_LOW)
digest_idx, exp_digest[digest_idx]), UVM_HIGH)
if (expected_digest_size == SHA2_256) begin
// only check till digest_idx = 7.
// Digests 8-15 are irrelevant for this digest size.
if (digest_idx < 8) begin
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx]);
end else begin
`DV_CHECK_EQ(real_digest_val, '0);
end
end else if (expected_digest_size == SHA2_512) begin
if (expected_digest_swap == 1'b0) begin
if (digest_idx % 2) begin // odd index then compare with smaller index
if (digest_idx % 2) begin // odd index then compare with smaller index
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx-1]);
end else begin
end else begin
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx+1]);
end
end
end else begin
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx]);
end
end else if (expected_digest_size == SHA2_384) begin
if (digest_idx > 11) begin
`DV_CHECK_EQ(real_digest_val, '0); // truncated digest words
end else begin
// only check till digest_idx = 11.
// Digests 12-15 are irrelevant/truncated for this digest size.
if (digest_idx < 11) begin
if (expected_digest_swap == 1'b0) begin
if (digest_idx % 2) begin // odd index then compare with smaller index
if (digest_idx % 2) begin // odd index then compare with smaller index
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx-1]);
end else begin
end else begin
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx+1]);
end
end
end else begin
`DV_CHECK_EQ(real_digest_val, exp_digest[digest_idx]);
end
Expand Down
8 changes: 2 additions & 6 deletions hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ constraint key_digest_c {
`DV_CHECK_STD_RANDOMIZE_FATAL(secret_val)
csr_wr(.ptr(ral.wipe_secret), .value(secret_val));
cfg.wipe_secret_triggered = 1;
`uvm_info(`gfn, $sformatf("wipe secret triggered"), UVM_LOW)
`uvm_info(`gfn, $sformatf("wiping secret triggered"), UVM_LOW)
endtask

// write msg to DUT, read status FIFO FULL and check intr FIFO FULL
Expand Down Expand Up @@ -367,19 +367,15 @@ constraint key_digest_c {
// since HMAC digest size is max 512 bits.
packed_exp_digest = {>>byte{exp_digest}};
if (cfg.clk_rst_vif.rst_n) begin
// can safely assume that `exp_digest` always has 16 elements
// since HMAC output digest size is 512 bits.
foreach (act_digest[i]) begin
`uvm_info(`gfn, $sformatf("Actual digest[%0d]: 0x%0h", i, act_digest[i]), UVM_HIGH)
`uvm_info(`gfn, $sformatf("Expected digest[%0d]: 0x%0h", i, packed_exp_digest[i]), UVM_HIGH)
end

// comparing for SHA-2 256
// comparing only digest[0] to digest [7] for SHA-2 256
foreach (act_digest[i]) begin
if (i < 8) begin
`DV_CHECK_EQ(act_digest[i], packed_exp_digest[i], $sformatf("for index %0d", i))
end else begin
`DV_CHECK_EQ(act_digest[i], '0);
end
end
end else begin
Expand Down
10 changes: 5 additions & 5 deletions hw/ip/hmac/dv/env/seq_lib/hmac_smoke_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class hmac_smoke_vseq extends hmac_base_vseq;
if (i != 1 && $urandom_range(0, 1)) rd_digest();

if (do_wipe_secret == WipeSecretBeforeKey) begin
`uvm_info(`gfn, $sformatf("wiping before key"), UVM_LOW)
`uvm_info(`gfn, $sformatf("wiping before key"), UVM_HIGH)
wipe_secrets();
// Check if digest data are corrupted by wiping secrets.
rd_digest();
Expand All @@ -120,7 +120,7 @@ class hmac_smoke_vseq extends hmac_base_vseq;
if (i != 1 && $urandom_range(0, 1)) rd_digest();

if (do_wipe_secret == WipeSecretBeforeStart) begin
`uvm_info(`gfn, $sformatf("wiping before start"), UVM_LOW)
`uvm_info(`gfn, $sformatf("wiping before start"), UVM_HIGH)
wipe_secrets();
// Here the wipe secret will only corrupt secret keys and current digests.
// If HMAC is not enabled, check if digest is corrupted.
Expand All @@ -147,7 +147,7 @@ class hmac_smoke_vseq extends hmac_base_vseq;
end
begin
if (do_wipe_secret == WipeSecretBeforeProcess) begin
`uvm_info(`gfn, $sformatf("wiping before process"), UVM_LOW)
`uvm_info(`gfn, $sformatf("wiping before process"), UVM_HIGH)
cfg.clk_rst_vif.wait_clks($urandom_range(0, msg.size() * 10));
wipe_secrets();
end
Expand Down Expand Up @@ -199,7 +199,7 @@ class hmac_smoke_vseq extends hmac_base_vseq;
end
begin
if (do_wipe_secret == WipeSecretBeforeDone) begin
`uvm_info(`gfn, $sformatf("wiping before done"), UVM_LOW)
`uvm_info(`gfn, $sformatf("wiping before done"), UVM_HIGH)

cfg.clk_rst_vif.wait_clks($urandom_range(0, 100));
wipe_secrets();
Expand All @@ -216,7 +216,7 @@ class hmac_smoke_vseq extends hmac_base_vseq;
if ($urandom_range(0, 1)) rd_msg_length();

// read digest from DUT
`uvm_info(`gfn, $sformatf("reading digest now"), UVM_HIGH)
`uvm_info(`gfn, $sformatf("reading digest"), UVM_LOW)
rd_digest();
end
endtask : body
Expand Down

0 comments on commit 58ec412

Please sign in to comment.