Skip to content

Commit

Permalink
[aes] Connect EDN interface
Browse files Browse the repository at this point in the history
Signed-off-by: Pirmin Vogel <[email protected]>
  • Loading branch information
vogelpi committed Jan 17, 2025
1 parent 6bff4e4 commit 4c22c90
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 3 deletions.
21 changes: 21 additions & 0 deletions src/aes/rtl/aes_clp_reg.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ addrmap aes_clp_reg {

} AES_VERSION[2];

/* ---- Entropy Interface Seed ---- */
reg {
name = "Entropy Interface Seed";
desc = "After reset and whenever firmware wants to re-initialize the Trivium stream cipher
primitive driving the EDN interface of AES, it has to perform 9 subsequent write
operations to this register to provide the 288-bit state seed for the Trivium
primitive.
It's fine to write the register while AES is busy and even while it's performing a
a reseed operation of the internal PRNGs via the EDN interface.

Note: Upon reset, the state of the Trivium primitive is initialized to a netlist
constant. The primitive thus always generates the same output after reset. It is the
job of firmware to provide a new state seed after reset.";

default hw = r;
default sw = w;
default swmod = true;

field {desc = "Entropy Interface Seed field";} ENTROPY_IF_SEED[32];
} ENTROPY_IF_SEED @0x00000110;

/* ---- AES Key Vault Control Reg ---- */
kv_read_ctrl_reg AES_KV_RD_KEY_CTRL @0x00000600;
kv_status_reg AES_KV_RD_KEY_STATUS;
Expand Down
34 changes: 34 additions & 0 deletions src/aes/rtl/aes_clp_reg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ module aes_clp_reg (
typedef struct packed{
logic [2-1:0]AES_NAME;
logic [2-1:0]AES_VERSION;
logic ENTROPY_IF_SEED;
logic AES_KV_RD_KEY_CTRL;
logic AES_KV_RD_KEY_STATUS;
struct packed{
Expand Down Expand Up @@ -105,6 +106,7 @@ module aes_clp_reg (
for(int i0=0; i0<2; i0++) begin
decoded_reg_strb.AES_VERSION[i0] = cpuif_req_masked & (cpuif_addr == 12'h108 + i0*12'h4);
end
decoded_reg_strb.ENTROPY_IF_SEED = cpuif_req_masked & (cpuif_addr == 12'h110);
decoded_reg_strb.AES_KV_RD_KEY_CTRL = cpuif_req_masked & (cpuif_addr == 12'h600);
decoded_reg_strb.AES_KV_RD_KEY_STATUS = cpuif_req_masked & (cpuif_addr == 12'h604);
decoded_reg_strb.intr_block_rf.global_intr_en_r = cpuif_req_masked & (cpuif_addr == 12'h800);
Expand Down Expand Up @@ -138,6 +140,12 @@ module aes_clp_reg (
// Field logic
//--------------------------------------------------------------------------
typedef struct packed{
struct packed{
struct packed{
logic [31:0] next;
logic load_next;
} ENTROPY_IF_SEED;
} ENTROPY_IF_SEED;
struct packed{
struct packed{
logic next;
Expand Down Expand Up @@ -342,6 +350,11 @@ module aes_clp_reg (
field_combo_t field_combo;

typedef struct packed{
struct packed{
struct packed{
logic [31:0] value;
} ENTROPY_IF_SEED;
} ENTROPY_IF_SEED;
struct packed{
struct packed{
logic value;
Expand Down Expand Up @@ -491,6 +504,27 @@ module aes_clp_reg (
} field_storage_t;
field_storage_t field_storage;

// Field: aes_clp_reg.ENTROPY_IF_SEED.ENTROPY_IF_SEED
always_comb begin
automatic logic [31:0] next_c;
automatic logic load_next_c;
next_c = field_storage.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value;
load_next_c = '0;
if(decoded_reg_strb.ENTROPY_IF_SEED && decoded_req_is_wr) begin // SW write
next_c = (field_storage.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
load_next_c = '1;
end
field_combo.ENTROPY_IF_SEED.ENTROPY_IF_SEED.next = next_c;
field_combo.ENTROPY_IF_SEED.ENTROPY_IF_SEED.load_next = load_next_c;
end

always_ff @(posedge clk) begin
if(field_combo.ENTROPY_IF_SEED.ENTROPY_IF_SEED.load_next) begin
field_storage.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value <= field_combo.ENTROPY_IF_SEED.ENTROPY_IF_SEED.next;
end
end
assign hwif_out.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value = field_storage.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value;
assign hwif_out.ENTROPY_IF_SEED.ENTROPY_IF_SEED.swmod = decoded_reg_strb.ENTROPY_IF_SEED && decoded_req_is_wr;
// Field: aes_clp_reg.AES_KV_RD_KEY_CTRL.read_en
always_comb begin
automatic logic [0:0] next_c;
Expand Down
10 changes: 10 additions & 0 deletions src/aes/rtl/aes_clp_reg_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ package aes_clp_reg_pkg;
aes_clp_reg__intr_block_t__in_t intr_block_rf;
} aes_clp_reg__in_t;

typedef struct packed{
logic [31:0] value;
logic swmod;
} aes_clp_reg__ENTROPY_IF_SEED__ENTROPY_IF_SEED__out_t;

typedef struct packed{
aes_clp_reg__ENTROPY_IF_SEED__ENTROPY_IF_SEED__out_t ENTROPY_IF_SEED;
} aes_clp_reg__ENTROPY_IF_SEED__out_t;

typedef struct packed{
logic value;
} kv_read_ctrl_reg__read_en__out_t;
Expand Down Expand Up @@ -142,6 +151,7 @@ package aes_clp_reg_pkg;
} aes_clp_reg__intr_block_t__out_t;

typedef struct packed{
aes_clp_reg__ENTROPY_IF_SEED__out_t ENTROPY_IF_SEED;
kv_read_ctrl_reg__out_t AES_KV_RD_KEY_CTRL;
aes_clp_reg__intr_block_t__out_t intr_block_rf;
} aes_clp_reg__out_t;
Expand Down
36 changes: 36 additions & 0 deletions src/aes/rtl/aes_clp_reg_uvm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,36 @@ package aes_clp_reg_uvm;
endfunction : build
endclass : aes_clp_reg__AES_VERSION

// Reg - aes_clp_reg::ENTROPY_IF_SEED
class aes_clp_reg__ENTROPY_IF_SEED extends uvm_reg;
protected uvm_reg_data_t m_current;
protected uvm_reg_data_t m_data;
protected bit m_is_read;

aes_clp_reg__ENTROPY_IF_SEED_bit_cg ENTROPY_IF_SEED_bit_cg[32];
aes_clp_reg__ENTROPY_IF_SEED_fld_cg fld_cg;
rand uvm_reg_field ENTROPY_IF_SEED;

function new(string name = "aes_clp_reg__ENTROPY_IF_SEED");
super.new(name, 32, build_coverage(UVM_CVR_ALL));
endfunction : new
extern virtual function void sample_values();
extern protected virtual function void sample(uvm_reg_data_t data,
uvm_reg_data_t byte_en,
bit is_read,
uvm_reg_map map);

virtual function void build();
this.ENTROPY_IF_SEED = new("ENTROPY_IF_SEED");
this.ENTROPY_IF_SEED.configure(this, 32, 0, "WO", 0, 'h0, 0, 1, 0);
if (has_coverage(UVM_CVR_REG_BITS)) begin
foreach(ENTROPY_IF_SEED_bit_cg[bt]) ENTROPY_IF_SEED_bit_cg[bt] = new();
end
if (has_coverage(UVM_CVR_FIELD_VALS))
fld_cg = new();
endfunction : build
endclass : aes_clp_reg__ENTROPY_IF_SEED

// Reg - kv_read_ctrl_reg
class kv_read_ctrl_reg extends uvm_reg;
protected uvm_reg_data_t m_current;
Expand Down Expand Up @@ -899,6 +929,7 @@ package aes_clp_reg_uvm;
class aes_clp_reg extends uvm_reg_block;
rand aes_clp_reg__AES_NAME AES_NAME[2];
rand aes_clp_reg__AES_VERSION AES_VERSION[2];
rand aes_clp_reg__ENTROPY_IF_SEED ENTROPY_IF_SEED;
rand kv_read_ctrl_reg AES_KV_RD_KEY_CTRL;
rand kv_status_reg AES_KV_RD_KEY_STATUS;
rand aes_clp_reg__intr_block_t intr_block_rf;
Expand All @@ -923,6 +954,11 @@ package aes_clp_reg_uvm;
this.AES_VERSION[i0].build();
this.default_map.add_reg(this.AES_VERSION[i0], 'h108 + i0*'h4);
end
this.ENTROPY_IF_SEED = new("ENTROPY_IF_SEED");
this.ENTROPY_IF_SEED.configure(this);

this.ENTROPY_IF_SEED.build();
this.default_map.add_reg(this.ENTROPY_IF_SEED, 'h110);
this.AES_KV_RD_KEY_CTRL = new("AES_KV_RD_KEY_CTRL");
this.AES_KV_RD_KEY_CTRL.configure(this);

Expand Down
53 changes: 50 additions & 3 deletions src/aes/rtl/aes_clp_wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ aes_clp_reg aes_clp_reg_inst (
);

edn_pkg::edn_rsp_t edn_i;

assign edn_i = '{edn_ack:edn_req.edn_req, edn_fips:0, edn_bus:'0}; //FIXME
logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] edn_bus;
assign edn_i = '{edn_ack:edn_req.edn_req, edn_fips:0, edn_bus:edn_bus};

//AES Engine
aes
Expand All @@ -211,7 +211,7 @@ aes_inst (
.clk_edn_i(clk),
.rst_edn_ni(reset_n),
.edn_o(edn_req),
.edn_i(edn_i), //FIXME
.edn_i(edn_i),

// Key manager (keymgr) key sideload interface
.keymgr_key_i(keymgr_key), //FIXME
Expand Down Expand Up @@ -319,5 +319,52 @@ always_ff @(posedge clk or negedge reset_n) begin
end
end

// Entropy interface
// We use a Trivium stream cipher primitive which is parameterized as follows:
// - It takes 32 bits of seed material at a time provided by firmware via the ENTROPY_IF_SEED
// register. To provide the full 288 bits required to reseed the entire Trivium state, firmware
// has to perform 9 subsequent writes to the register.
// - It delivers 32 bits per clock cycle to AES via the EDN interface. AES will repeatedly request
// fresh entropy via this interface. The rate depends on the value of
// CTRL_SHADOWED.PRNG_RESEED_RATE.
//
// Note: Upon reset, the state of the Trivium primitive is initialized to a netlist constant. The
// primitive thus always generates the same output after reset. It is the job of firmware to
// provide a new state seed after reset.
logic [AHB_DATA_WIDTH-1:0] trivium_seed;
logic trivium_seed_en;
always_ff @(posedge clk or negedge reset_n) begin
if (~reset_n) begin
trivium_seed_en <= 1'b0;
end else begin
trivium_seed_en <= hwif_out.ENTROPY_IF_SEED.ENTROPY_IF_SEED.swmod;
end
end
assign trivium_seed = hwif_out.ENTROPY_IF_SEED.ENTROPY_IF_SEED.value;

calpitra_prim_trivium #(
.OutputWidth (edn_pkg::ENDPOINT_BUS_WIDTH),
.SeedType (prim_trivium_pkg::SeedTypeStatePartial),
.PartialSeedWidth(AHB_DATA_WIDTH)
)
u_caliptra_prim_trivium
(
.clk_i(clk),
.rst_ni(reset_n),

.en_i (edn_req.edn_req),
.allow_lockup_i ('0), // Not used.
.seed_en_i (trivium_seed_en),
.seed_done_o (), // Not used.
.seed_req_o (), // Not used.
.seed_ack_i (trivium_seed_en),
.seed_key_i ('0), // Not used.
.seed_iv_i ('0), // Not used.
.seed_state_full_i ('0), // Not used.
.seed_state_partial_i(trivium_seed),

.key_o(edn_bus),
.err_o()
);

endmodule

0 comments on commit 4c22c90

Please sign in to comment.