Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions hw/ip/rram_ctrl/dv/bkdr/rram_ctrl_bkdr_util.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CAPI=2:
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: lowrisc:dv:rram_ctrl_bkdr_util:0.1
description: "Backdoor read/write rram memory for DV"

filesets:
files_dv:
depend:
- lowrisc:opentitan:bus_params_pkg
- lowrisc:dv:dv_utils
- lowrisc:dv:crypto_dpi_prince:0.1
- lowrisc:dv:crypto_dpi_present:0.1
- lowrisc:prim:secded:0.1
- lowrisc:ip:rram_ctrl_pkg
- lowrisc:dv:mem_bkdr_util
files:
- rram_ctrl_bkdr_util_pkg.sv
- rram_ctrl_bkdr_util.sv: {is_include_file: true}
file_type: systemVerilogSource

targets:
default:
filesets:
- files_dv
186 changes: 186 additions & 0 deletions hw/ip/rram_ctrl/dv/bkdr/rram_ctrl_bkdr_util.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// Specialization of the `mem_bkdr_util` class for RRAM memory

class rram_ctrl_bkdr_util extends mem_bkdr_util;

localparam int unsigned RramDataWidth = rram_ctrl_pkg::DataWidth;
localparam int unsigned RramKeySize = rram_ctrl_pkg::KeySize;
localparam int unsigned RramAddrW = rram_ctrl_pkg::AddrW;
localparam int unsigned RramStagesPerCycle = RramDataWidth / rram_ctrl_pkg::GfMultCycles;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this doesn't divide cleanly? (And do we care?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a requirement of the gfmultiplier hardware module. so it must be a clean division

localparam int unsigned RramNumRoundsHalf = crypto_dpi_prince_pkg::NumRoundsHalf;
localparam int unsigned RramDataByteWidth = $clog2(RramDataWidth / 8);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this doesn't divide cleanly? Do you want a +7 here? (Or maybe a check in the constructor? "These parameters don't make sense, so you can't make the class today")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RramDataWidth is always a multiple of a byte.

But I guess I can add a check to verify the parameters


// A GF-multiplier stage matrix, as produced by rram_gen_matrix() and consumed by
// rram_galois_multiply().
typedef bit [RramStagesPerCycle-1:0][RramDataWidth-1:0] rram_gf_matrix_t;

// Initialize the class instance.
//
// All arguments are forwarded unmodified to `mem_bkdr_util::new()`
//
// name UVM object instance name.
// path Hierarchical HDL path to the memory.
// depth The number of memory rows.
// n_bits The total size of the memory in bits.
// err_detection_scheme The error detection scheme implemented for the memory. This class
// only supports `ErrDetectionNone` for now (checked below).
// row_adapter Adapter to access the internal row of a memory, for integrators
// with a custom memory architecture - not used.
// num_prince_rounds_half The number of PRINCE half-rounds - not used
// extra_bits_per_subword The width of any additional metadata that is not captured in the
// secded package - not used.
// system_base_addr Base address of the memory.
function new(string name = "", string path, int unsigned depth,
longint unsigned n_bits, err_detection_e err_detection_scheme,
mem_bkdr_util_row_adapter row_adapter = null,
int num_prince_rounds_half = 3,
int extra_bits_per_subword = 0, int unsigned system_base_addr = 0);

super.new(name, path, depth, n_bits, err_detection_scheme, row_adapter,
num_prince_rounds_half, extra_bits_per_subword, system_base_addr);

// No ECC for now. once added, the functions below need to be adjusted
`DV_CHECK_EQ_FATAL(err_detection_scheme, mem_bkdr_util_pkg::ErrDetectionNone)

// The GF multiplier decomposition below mirrors the `prim_gf_mult` hardware, which requires
// the datapath width to divide evenly into the number of multiplier stages.
`DV_CHECK_EQ_FATAL(RramDataWidth % rram_ctrl_pkg::GfMultCycles, 0,
"RramDataWidth must be a multiple of GfMultCycles")
`DV_CHECK_EQ_FATAL(RramDataWidth % 8, 0, "RramDataWidth must be a multiple of bytes")
endfunction

// Randomize the memory
virtual function void randomize_mem();
`uvm_info(`gfn, "Randomizing rram mem contents", UVM_LOW)
for (int i = 0; i < depth; i++) begin
uvm_hdl_data_t data;
`DV_CHECK_STD_RANDOMIZE_FATAL(data, "Randomization failed!", path)
write(i * bytes_per_word, data);
end
endfunction

static function bit [RramDataWidth-1:0] rram_gf_mult2(bit [RramDataWidth-1:0] operand);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs a documentation comment (which should describe the operand argument as well as the point of the function)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just the inner part of the gfmultiplier. I also don't really know what it is doing in detail. I took it over from flash_ctrl

bit [RramDataWidth-1:0] mult_out;

mult_out = operand[RramDataWidth-1] ? (operand << 1) ^ rram_ctrl_pkg::ScrambleIPoly :
(operand << 1);
return mult_out;
endfunction

// Generate the per-stage GF-multiplier matrix consumed by rram_galois_multiply(), mirroring
// `prim_gf_mult`'s `gen_matrix` step.
// `seed` is the running GF value carried over from the previous cycle's last row; `init` is set
// for the very first iteration, in which case `seed` is used directly as row 0 instead of first
// being multiplied by x. Each subsequent row is the previous row multiplied by x (rram_gf_mult2).
static function rram_gf_matrix_t rram_gen_matrix(bit [RramDataWidth-1:0] seed, bit init);
rram_gf_matrix_t matrix_out;

matrix_out[0] = init ? seed : rram_gf_mult2(seed);
for (int i = 1; i < RramStagesPerCycle; i++) begin
matrix_out[i] = rram_gf_mult2(matrix_out[i-1]);
end
return matrix_out;
endfunction

// Compute the tweak for the XEX cipher. Tweak = GfMult128(addr, addr_key)
static function bit [RramDataWidth-1:0] rram_galois_multiply(bit [RramKeySize-1:0] addr_key,
bit [RramAddrW-1:0] addr);
bit [RramDataWidth-1:0] total_product = '0;
bit [RramDataWidth-1:0] next_seed;

// Initial seed
next_seed = {'0, addr};

for (int j = 0; j < rram_ctrl_pkg::GfMultCycles; j++) begin
rram_gf_matrix_t current_matrix;
bit [RramDataWidth-1:0] mult_out = '0;

// Generate matrix for this chunk
// Use init = 1 for the very first chunk, init = 0 for subsequent ones
current_matrix = rram_gen_matrix(next_seed, (j == 0));
for (int i = 0; i < RramStagesPerCycle; i++) begin
if (addr_key[(j * RramStagesPerCycle) + i]) begin
mult_out = mult_out ^ current_matrix[i];
end
end
// Accumulate result
total_product = total_product ^ mult_out;
// Prepare seed for next loop: the last row of current matrix
next_seed = current_matrix[RramStagesPerCycle-1];
end

return total_product;
endfunction

// Scramble a single RRAM word using the XEX cipher:
// 1. Compute the tweak (gfmult128(addr_key, addr))
// 2. Apply the tweak
// 3. Encrypt the data with the data_key
// 4. Remove the tweak
function bit [RramDataWidth-1:0] rram_scramble_data(bit [RramDataWidth-1:0] data,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs documenting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

bit [RramAddrW-1:0] word_addr,
bit [RramKeySize-1:0] rram_addr_key,
bit [RramKeySize-1:0] rram_data_key);
bit [RramDataWidth-1:0] masked_data;
bit [RramDataWidth-1:0] scrambled_data;
bit [RramDataWidth-1:0] mask;

mask = rram_galois_multiply(rram_addr_key, word_addr);
masked_data = data ^ mask;

for (int k = 0; k < 2; k++) begin
bit [RramDataWidth/2-1:0] cipher_in;
bit [RramNumRoundsHalf-1:0][RramDataWidth/2-1:0] cipher_out;
for (int i = 0; i < RramDataWidth/2; i++) begin
cipher_in[i] = masked_data[2*i+k];
end
crypto_dpi_prince_pkg::sv_dpi_prince_encrypt(.plaintext(cipher_in),
.key(rram_data_key),
.old_key_schedule(0),
.ciphertext(cipher_out));
for (int i = 0; i < RramDataWidth/2; i++) begin
scrambled_data[2*i+k] = cipher_out[RramNumRoundsHalf-1][i];
end
end
return scrambled_data ^ mask;
endfunction

// Descramble a single RRAM word using the XEX cipher:
// 1. Compute the tweak (gfmult128(addr_key, addr))
// 2. Apply the tweak
// 3. Decrypt the data with the data_key
// 4. Remove the tweak
function bit [RramDataWidth-1:0] rram_descramble_data(bit [RramDataWidth-1:0] data,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs documenting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

bit [RramAddrW-1:0] word_addr,
bit [RramKeySize-1:0] rram_addr_key,
bit [RramKeySize-1:0] rram_data_key);
bit [RramDataWidth-1:0] masked_data;
bit [RramDataWidth-1:0] descrambled_data;
bit [RramDataWidth-1:0] mask;

mask = rram_galois_multiply(rram_addr_key, word_addr);
masked_data = data ^ mask;

for (int k = 0; k < 2; k++) begin
bit [RramDataWidth/2-1:0] cipher_in;
bit [RramDataWidth/2-1:0] cipher_out;
for (int i = 0; i < RramDataWidth/2; i++) begin
cipher_in[i] = masked_data[2*i+k];
end
cipher_out = crypto_dpi_prince_pkg::c_dpi_prince_decrypt(cipher_in,
rram_data_key[127:64],
rram_data_key[63:0],
RramNumRoundsHalf,
0);
for (int i = 0; i < RramDataWidth/2; i++) begin
descrambled_data[2*i+k] = cipher_out[i];
end
end

return descrambled_data ^ mask;
endfunction

endclass
20 changes: 20 additions & 0 deletions hw/ip/rram_ctrl/dv/bkdr/rram_ctrl_bkdr_util_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

package rram_ctrl_bkdr_util_pkg;
// dep packages
import bus_params_pkg::BUS_AW;
import dv_utils_pkg::uint32_t, dv_utils_pkg::addr_range_t;
import lc_ctrl_state_pkg::*;
import mem_bkdr_util_pkg::*;
import prim_secded_pkg::*;
import uvm_pkg::*;

// macro includes
`include "uvm_macros.svh"
`include "dv_macros.svh"

// sources
`include "rram_ctrl_bkdr_util.sv"
endpackage
Loading