[aes] Use one-hot encoding for OPERATION field in main control register
This is related to lowRISC/OpenTitan#10422.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/data/aes.hjson b/hw/ip/aes/data/aes.hjson
index aaf4603..3f34e59 100644
--- a/hw/ip/aes/data/aes.hjson
+++ b/hw/ip/aes/data/aes.hjson
@@ -372,15 +372,31 @@
update_err_alert: "recov_ctrl_update_err",
storage_err_alert: "fatal_fault",
fields: [
- { bits: "0",
+ { bits: "1:0",
name: "OPERATION",
- resval: "0",
+ resval: "0x1",
+ hwaccess: "hrw",
desc: '''
- Select encryption(0) or decryption(1) operation of AES unit.
+ 2-bit one-hot field to select the operation of AES unit.
+ Invalid input values, i.e., values with multiple bits set and value 2'b00, are mapped to AES_ENCRYPTION (2'b01).
'''
+ enum: [
+ { value: "1",
+ name: "AES_ENC",
+ desc: '''
+ 2'b01: Encryption.
+ '''
+ },
+ { value: "2",
+ name: "AES_DEC",
+ desc: '''
+ 2'b10: Decryption.
+ '''
+ },
+ ]
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_operation"]
}
- { bits: "6:1",
+ { bits: "7:2",
name: "MODE",
resval: "0x20",
hwaccess: "hrw",
@@ -428,7 +444,7 @@
]
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_mode"]
}
- { bits: "9:7",
+ { bits: "10:8",
name: "KEY_LEN",
resval: "1",
hwaccess: "hrw",
@@ -460,7 +476,7 @@
]
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_key_len"]
}
- { bits: "10",
+ { bits: "11",
name: "SIDELOAD",
resval: "0",
desc: '''
@@ -468,7 +484,7 @@
'''
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_sideload"]
}
- { bits: "13:11",
+ { bits: "14:12",
name: "PRNG_RESEED_RATE",
resval: "1",
hwaccess: "hrw",
@@ -499,7 +515,7 @@
]
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_prng_reseed_rate"]
}
- { bits: "14",
+ { bits: "15",
name: "MANUAL_OPERATION",
resval: "0"
desc: '''
@@ -512,7 +528,7 @@
'''
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_reg_shadowed.u_ctrl_reg_shadowed_manual_operation"]
}
- { bits: "15",
+ { bits: "16",
name: "FORCE_ZERO_MASKS",
resval: "0"
desc: '''
diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv
index 1a1e4d8..9b0ab31 100644
--- a/hw/ip/aes/dv/env/aes_scoreboard.sv
+++ b/hw/ip/aes/dv/env/aes_scoreboard.sv
@@ -529,6 +529,7 @@
bit [3:0][31:0] tmp_output;
forever begin
+ bit operation;
aes_message_item msg;
msg_fifo.get(msg);
`uvm_info(`gfn, $sformatf("model %b, operation: %b, mode %06b, IV %h, key_len %03b, key share0 %h, key share1 %h ",
@@ -540,7 +541,9 @@
msg.alloc_predicted_msg();
//ref-model / opration / chipher mode / IV / key_len / key /data i /data o //
- c_dpi_aes_crypt_message(cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv,
+ operation = msg.aes_operation == AES_ENC ? 1'b0 :
+ msg.aes_operation == AES_DEC ? 1'b1 : 1'b0;
+ c_dpi_aes_crypt_message(cfg.ref_model, operation, msg.aes_mode, msg.aes_iv,
msg.aes_keylen, msg.aes_key[0] ^ msg.aes_key[1],
msg.input_msg, msg.predicted_msg);
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
index 1d83d4e..9d477f5 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
@@ -56,9 +56,9 @@
// Wait for DUT ready
csr_spinwait(.ptr(ral.status.idle) , .exp_data(1'b1));
// initialize control register
- aes_ctrl[0] = 0; // set to encryption
- aes_ctrl[6:1] = aes_pkg::AES_ECB; // 6'b00_0001
- aes_ctrl[9:7] = aes_pkg::AES_128; // set to 128b key
+ aes_ctrl[1:0] = aes_pkg::AES_ENC; // 2'b01
+ aes_ctrl[7:2] = aes_pkg::AES_ECB; // 6'b00_0001
+ aes_ctrl[10:8] = aes_pkg::AES_128; // 3'b001
csr_wr(.ptr(ral.ctrl_shadowed), .value(aes_ctrl), .en_shadow_wr(1'b1), .blocking(1));
// initialize aux control register and lock it
// This is a temporary workaround until the aux control register is properly supported.
@@ -94,7 +94,7 @@
endtask // prng_reseed
- virtual task set_operation(bit operation);
+ virtual task set_operation(bit [1:0] operation);
ral.ctrl_shadowed.operation.set(operation);
csr_update(.csr(ral.ctrl_shadowed), .en_shadow_wr(1'b1), .blocking(1));
endtask // set_operation
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
index 23f606a..02806b7 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
@@ -10,9 +10,6 @@
`uvm_object_new
- parameter bit ENCRYPT = 1'b0;
- parameter bit DECRYPT = 1'b1;
-
bit [3:0] [31:0] plain_text = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
logic [255:0] init_key [2] = '{256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF, 256'h0};
bit [3:0] [31:0] cypher_text;
@@ -31,7 +28,7 @@
`uvm_info(`gfn, $sformatf(" \n\t ---|setting operation to encrypt"), UVM_HIGH)
// set operation to encrypt
- set_operation(ENCRYPT);
+ set_operation(AES_ENC);
`uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY \n\t ----| SHARE0 %02h \n\t ---| SHARE1 %02h ", init_key[0], init_key[1]), UVM_HIGH)
write_key(init_key, do_b2b);
@@ -54,7 +51,7 @@
cfg.clk_rst_vif.wait_clks(20);
// set aes to decrypt
- set_operation(DECRYPT);
+ set_operation(AES_DEC);
cfg.clk_rst_vif.wait_clks(20);
`uvm_info(`gfn, $sformatf("\n\t ---| WRITING INIT KEY \n\t ----| SHARE0 %02h \n\t ---| SHARE1 %02h ", init_key[0], init_key[1]), UVM_HIGH)
write_key(init_key, do_b2b);
diff --git a/hw/ip/aes/rtl/aes_cipher_control.sv b/hw/ip/aes/rtl/aes_cipher_control.sv
index 425d935..7cd503a 100644
--- a/hw/ip/aes/rtl/aes_cipher_control.sv
+++ b/hw/ip/aes/rtl/aes_cipher_control.sv
@@ -40,6 +40,7 @@
output logic data_out_clear_o,
input logic mux_sel_err_i,
input logic sp_enc_err_i,
+ input logic op_err_i,
output logic alert_o,
// Control signals for masking PRNG
@@ -176,6 +177,7 @@
.mux_sel_err_i ( mux_sel_err ),
.sp_enc_err_i ( sp_enc_err ),
.rnd_ctr_err_i ( rnd_ctr_err ),
+ .op_err_i ( op_err_i ),
.alert_o ( mr_alert[i] ), // OR-combine
.prng_update_o ( mr_prng_update[i] ), // OR-combine
@@ -242,6 +244,7 @@
.mux_sel_err_i ( mux_sel_err ),
.sp_enc_err_i ( sp_enc_err ),
.rnd_ctr_err_i ( rnd_ctr_err ),
+ .op_err_i ( op_err_i ),
.alert_o ( mr_alert[i] ), // OR-combine
.prng_update_o ( mr_prng_update[i] ), // OR-combine
@@ -538,6 +541,9 @@
////////////////
// Selectors must be known/valid
- `ASSERT_KNOWN(AesCiphOpKnown, op_i)
+ `ASSERT(AesCiphOpValid, cfg_valid_i |-> op_i inside {
+ CIPH_FWD,
+ CIPH_INV
+ })
endmodule
diff --git a/hw/ip/aes/rtl/aes_cipher_control_fsm.sv b/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
index 566b996..bb391e8 100644
--- a/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
+++ b/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
@@ -35,6 +35,7 @@
input logic data_out_clear_i,
input logic mux_sel_err_i,
input logic sp_enc_err_i,
+ input logic op_err_i,
output logic alert_o,
// Control signals for masking PRNG
@@ -226,7 +227,8 @@
// Load full key
key_full_sel_o = dec_key_gen_i ? KEY_FULL_ENC_INIT :
(op_i == CIPH_FWD) ? KEY_FULL_ENC_INIT :
- KEY_FULL_DEC_INIT;
+ (op_i == CIPH_INV) ? KEY_FULL_DEC_INIT :
+ KEY_FULL_ENC_INIT;
key_full_we_o = 1'b1;
// Load num_rounds, initialize round counters.
@@ -304,7 +306,8 @@
prng_reseed_req_o = Masking & prng_reseed_q_i & ~prng_reseed_done_q;
// Select round key: direct or mixed (equivalent inverse cipher)
- round_key_sel_o = (op_i == CIPH_FWD) ? ROUND_KEY_DIRECT : ROUND_KEY_MIXED;
+ round_key_sel_o = (op_i == CIPH_FWD) ? ROUND_KEY_DIRECT :
+ (op_i == CIPH_INV) ? ROUND_KEY_MIXED : ROUND_KEY_DIRECT;
// Advance in sync with SubBytes and KeyExpand. Based on the S-Box implementation, both can
// take multiple cycles to finish. Wait for handshake. The DOM S-Boxes consume fresh PRD
@@ -382,7 +385,7 @@
// Perform both handshakes simultaneously.
advance = sub_bytes_out_req_i | dec_key_gen_q_i;
sub_bytes_en_o = ~dec_key_gen_q_i;
- out_valid_o = (mux_sel_err_i || sp_enc_err_i) ? 1'b0 :
+ out_valid_o = (mux_sel_err_i || sp_enc_err_i || op_err_i) ? 1'b0 :
Masking ? (prng_reseed_q_i ? prng_reseed_done_q & advance : advance) : advance;
// Stop updating the cycle counter once we have valid output.
@@ -466,7 +469,7 @@
// Unconditionally jump into the terminal error state in case a mux selector or a sparsely
// encoded signal becomes invalid, or in case we have detected a fault in the round counter.
- if (mux_sel_err_i || sp_enc_err_i || rnd_ctr_err_i) begin
+ if (mux_sel_err_i || sp_enc_err_i || rnd_ctr_err_i || op_err_i) begin
aes_cipher_ctrl_ns = ERROR;
end
end
@@ -513,7 +516,10 @@
////////////////
// Selectors must be known/valid
- `ASSERT_KNOWN(AesCiphOpKnown, op_i)
+ `ASSERT(AesCiphOpValid, cfg_valid_i |-> op_i inside {
+ CIPH_FWD,
+ CIPH_INV
+ })
`ASSERT(AesKeyLenValid, cfg_valid_i |-> key_len_i inside {
AES_128,
AES_192,
diff --git a/hw/ip/aes/rtl/aes_cipher_control_fsm_n.sv b/hw/ip/aes/rtl/aes_cipher_control_fsm_n.sv
index 629a689..fe20f41 100644
--- a/hw/ip/aes/rtl/aes_cipher_control_fsm_n.sv
+++ b/hw/ip/aes/rtl/aes_cipher_control_fsm_n.sv
@@ -39,6 +39,7 @@
input logic mux_sel_err_i,
input logic sp_enc_err_i,
input logic rnd_ctr_err_i,
+ input logic op_err_i,
output logic alert_o,
// Control signals for masking PRNG
@@ -103,6 +104,7 @@
mux_sel_err_i,
sp_enc_err_i,
rnd_ctr_err_i,
+ op_err_i,
prng_reseed_ack_i,
sub_bytes_out_req_ni,
key_expand_out_req_ni,
@@ -132,6 +134,7 @@
mux_sel_err_i,
sp_enc_err_i,
rnd_ctr_err_i,
+ op_err_i,
prng_reseed_ack_i,
sub_bytes_out_req_ni,
key_expand_out_req_ni,
@@ -154,31 +157,32 @@
.out_o(in_buf)
);
- logic in_valid_n;
- logic out_ready_n;
- logic cfg_valid;
- logic op_raw;
- ciph_op_e op;
- key_len_e key_len;
- logic crypt_n;
- logic dec_key_gen_n;
- logic prng_reseed;
- logic key_clear;
- logic data_out_clear;
- logic mux_sel_err;
- logic sp_enc_err;
- logic rnd_ctr_err;
- logic prng_reseed_ack;
- logic sub_bytes_out_req_n;
- logic key_expand_out_req_n;
- logic [3:0] rnd_ctr_q;
- logic [3:0] rnd_ctr_rem_q;
- logic [3:0] num_rounds_q;
- logic crypt_q_n;
- logic dec_key_gen_q_n;
- logic prng_reseed_q;
- logic key_clear_q;
- logic data_out_clear_q;
+ logic in_valid_n;
+ logic out_ready_n;
+ logic cfg_valid;
+ ciph_op_e op;
+ logic [$bits(op)-1:0] op_raw;
+ key_len_e key_len;
+ logic crypt_n;
+ logic dec_key_gen_n;
+ logic prng_reseed;
+ logic key_clear;
+ logic data_out_clear;
+ logic mux_sel_err;
+ logic sp_enc_err;
+ logic rnd_ctr_err;
+ logic op_err;
+ logic prng_reseed_ack;
+ logic sub_bytes_out_req_n;
+ logic key_expand_out_req_n;
+ logic [3:0] rnd_ctr_q;
+ logic [3:0] rnd_ctr_rem_q;
+ logic [3:0] num_rounds_q;
+ logic crypt_q_n;
+ logic dec_key_gen_q_n;
+ logic prng_reseed_q;
+ logic key_clear_q;
+ logic data_out_clear_q;
assign {in_valid_n,
out_ready_n,
@@ -193,6 +197,7 @@
mux_sel_err,
sp_enc_err,
rnd_ctr_err,
+ op_err,
prng_reseed_ack,
sub_bytes_out_req_n,
key_expand_out_req_n,
@@ -268,6 +273,7 @@
.mux_sel_err_i ( mux_sel_err ),
.sp_enc_err_i ( sp_enc_err ),
.rnd_ctr_err_i ( rnd_ctr_err ),
+ .op_err_i ( op_err ),
.alert_o ( alert ),
.prng_update_o ( prng_update ),
diff --git a/hw/ip/aes/rtl/aes_cipher_control_fsm_p.sv b/hw/ip/aes/rtl/aes_cipher_control_fsm_p.sv
index adcb9ae..a31c2eb 100644
--- a/hw/ip/aes/rtl/aes_cipher_control_fsm_p.sv
+++ b/hw/ip/aes/rtl/aes_cipher_control_fsm_p.sv
@@ -35,6 +35,7 @@
input logic mux_sel_err_i,
input logic sp_enc_err_i,
input logic rnd_ctr_err_i,
+ input logic op_err_i,
output logic alert_o,
// Control signals for masking PRNG
@@ -99,6 +100,7 @@
mux_sel_err_i,
sp_enc_err_i,
rnd_ctr_err_i,
+ op_err_i,
prng_reseed_ack_i,
sub_bytes_out_req_i,
key_expand_out_req_i,
@@ -128,6 +130,7 @@
mux_sel_err_i,
sp_enc_err_i,
rnd_ctr_err_i,
+ op_err_i,
prng_reseed_ack_i,
sub_bytes_out_req_i,
key_expand_out_req_i,
@@ -150,31 +153,32 @@
.out_o(in_buf)
);
- logic in_valid;
- logic out_ready;
- logic cfg_valid;
- logic op_raw;
- ciph_op_e op;
- key_len_e key_len;
- logic crypt;
- logic dec_key_gen;
- logic prng_reseed;
- logic key_clear;
- logic data_out_clear;
- logic mux_sel_err;
- logic sp_enc_err;
- logic rnd_ctr_err;
- logic prng_reseed_ack;
- logic sub_bytes_out_req;
- logic key_expand_out_req;
- logic [3:0] rnd_ctr_q;
- logic [3:0] rnd_ctr_rem_q;
- logic [3:0] num_rounds_q;
- logic crypt_q;
- logic dec_key_gen_q;
- logic prng_reseed_q;
- logic key_clear_q;
- logic data_out_clear_q;
+ logic in_valid;
+ logic out_ready;
+ logic cfg_valid;
+ ciph_op_e op;
+ logic [$bits(op)-1:0] op_raw;
+ key_len_e key_len;
+ logic crypt;
+ logic dec_key_gen;
+ logic prng_reseed;
+ logic key_clear;
+ logic data_out_clear;
+ logic mux_sel_err;
+ logic sp_enc_err;
+ logic rnd_ctr_err;
+ logic op_err;
+ logic prng_reseed_ack;
+ logic sub_bytes_out_req;
+ logic key_expand_out_req;
+ logic [3:0] rnd_ctr_q;
+ logic [3:0] rnd_ctr_rem_q;
+ logic [3:0] num_rounds_q;
+ logic crypt_q;
+ logic dec_key_gen_q;
+ logic prng_reseed_q;
+ logic key_clear_q;
+ logic data_out_clear_q;
assign {in_valid,
out_ready,
@@ -189,6 +193,7 @@
mux_sel_err,
sp_enc_err,
rnd_ctr_err,
+ op_err,
prng_reseed_ack,
sub_bytes_out_req,
key_expand_out_req,
@@ -260,6 +265,7 @@
.mux_sel_err_i ( mux_sel_err ),
.sp_enc_err_i ( sp_enc_err ),
.rnd_ctr_err_i ( rnd_ctr_err ),
+ .op_err_i ( op_err ),
.alert_o ( alert ),
.prng_update_o ( prng_update ),
diff --git a/hw/ip/aes/rtl/aes_cipher_core.sv b/hw/ip/aes/rtl/aes_cipher_core.sv
index 759b2e0..ca031d1 100644
--- a/hw/ip/aes/rtl/aes_cipher_core.sv
+++ b/hw/ip/aes/rtl/aes_cipher_core.sv
@@ -159,6 +159,7 @@
state_sel_e state_sel;
logic state_sel_err;
+ ciph_op_e op;
sp2v_e sub_bytes_en;
sp2v_e sub_bytes_out_req;
sp2v_e sub_bytes_out_ack;
@@ -213,8 +214,10 @@
round_key_sel_e round_key_sel;
logic round_key_sel_err;
+ logic cfg_valid;
logic mux_sel_err;
logic sp_enc_err_d, sp_enc_err_q;
+ logic op_err;
// Pseudo-random data for clearing and masking purposes
logic [127:0] prd_clearing_128 [NumShares];
@@ -238,6 +241,21 @@
end
end
+ // op_i is one-hot encoded. Check the provided value and use the checked version internally.
+
+ // This primitive is used to place a size-only constraint on the
+ // buffers to act as a synthesis optimization barrier.
+ logic [$bits(ciph_op_e)-1:0] op_raw;
+ prim_buf #(
+ .Width($bits(ciph_op_e))
+ ) u_prim_buf_op (
+ .in_i(op_i),
+ .out_o(op_raw)
+ );
+ assign op = ciph_op_e'(op_raw);
+ assign op_err = ~(op == CIPH_FWD || op == CIPH_INV);
+ assign cfg_valid = cfg_valid_i & ~op_err;
+
//////////
// Data //
//////////
@@ -356,7 +374,7 @@
.en_i ( sub_bytes_en ),
.out_req_o ( sub_bytes_out_req ),
.out_ack_i ( sub_bytes_out_ack ),
- .op_i ( op_i ),
+ .op_i ( op ),
.data_i ( state_q[0] ),
.mask_i ( sb_in_mask ),
.prd_i ( prd_sub_bytes ),
@@ -375,13 +393,13 @@
end
aes_shift_rows u_aes_shift_rows (
- .op_i ( op_i ),
+ .op_i ( op ),
.data_i ( shift_rows_in[s] ),
.data_o ( shift_rows_out[s] )
);
aes_mix_columns u_aes_mix_columns (
- .op_i ( op_i ),
+ .op_i ( op ),
.data_i ( shift_rows_out[s] ),
.data_o ( mix_columns_out[s] )
);
@@ -448,7 +466,7 @@
) u_aes_key_expand (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
- .cfg_valid_i ( cfg_valid_i ),
+ .cfg_valid_i ( cfg_valid ),
.op_i ( key_expand_op ),
.en_i ( key_expand_en ),
.out_req_o ( key_expand_out_req ),
@@ -509,8 +527,8 @@
.out_valid_o ( out_valid_o ),
.out_ready_i ( out_ready_i ),
- .cfg_valid_i ( cfg_valid_i ),
- .op_i ( op_i ),
+ .cfg_valid_i ( cfg_valid ),
+ .op_i ( op ),
.key_len_i ( key_len_i ),
.crypt_i ( crypt_i ),
.crypt_o ( crypt_o ),
@@ -524,6 +542,7 @@
.data_out_clear_o ( data_out_clear_o ),
.mux_sel_err_i ( mux_sel_err ),
.sp_enc_err_i ( sp_enc_err_q ),
+ .op_err_i ( op_err ),
.alert_o ( alert_o ),
.prng_update_o ( prd_masking_upd ),
diff --git a/hw/ip/aes/rtl/aes_control_fsm.sv b/hw/ip/aes/rtl/aes_control_fsm.sv
index 622b58a..a680119 100644
--- a/hw/ip/aes/rtl/aes_control_fsm.sv
+++ b/hw/ip/aes/rtl/aes_control_fsm.sv
@@ -171,6 +171,7 @@
logic cfg_valid;
logic no_alert;
+ logic cipher_op_err;
logic start_common, start_ecb, start_cbc, start_cfb, start_ofb, start_ctr;
logic start;
logic finish;
@@ -212,6 +213,9 @@
assign cfg_valid = ~((mode_i == AES_NONE) | ctrl_err_storage_i);
assign no_alert = ~alert_fatal_i;
+ // cipher_op_i is obtained from the configuration of the control register with additional logic.
+ assign cipher_op_err = ~(cipher_op_i == CIPH_FWD || cipher_op_i == CIPH_INV);
+
// Check common start conditions. These are needed for any mode, unless we are running in
// manual mode.
assign start_common = key_init_ready & data_in_new &
@@ -520,7 +524,8 @@
// let data propagate in case of mux selector or sparsely encoded signals taking on
// invalid values.
cipher_out_ready_o = finish;
- cipher_out_done = finish & cipher_out_valid_i & ~mux_sel_err_i & ~sp_enc_err_i;
+ cipher_out_done = finish & cipher_out_valid_i &
+ ~mux_sel_err_i & ~sp_enc_err_i & ~cipher_op_err;
// Signal if the cipher core is stalled (because previous output has not yet been read).
stall = ~finish & cipher_out_valid_i;
@@ -602,7 +607,7 @@
if (cipher_data_out_clear_i) begin
// Clear output data and the trigger bit. Don't release data from cipher core in case
// of mux selector or sparsely encoded signals taking on invalid values.
- data_out_we_o = ~mux_sel_err_i & ~sp_enc_err_i;
+ data_out_we_o = ~mux_sel_err_i & ~sp_enc_err_i & ~cipher_op_err;
data_out_clear_we = 1'b1;
end
@@ -623,7 +628,8 @@
// Unconditionally jump into the terminal error state in case a mux selector or a sparsely
// encoded signal becomes invalid, or if the life cycle controller triggers an escalation.
- if (mux_sel_err_i || sp_enc_err_i || lc_escalate_en_i != lc_ctrl_pkg::Off) begin
+ if (mux_sel_err_i || sp_enc_err_i || cipher_op_err ||
+ lc_escalate_en_i != lc_ctrl_pkg::Off) begin
aes_ctrl_ns = ERROR;
end
end
@@ -856,8 +862,14 @@
AES_CTR,
AES_NONE
})
- `ASSERT_KNOWN(AesOpKnown, op_i)
- `ASSERT_KNOWN(AesCiphOpKnown, cipher_op_i)
+ `ASSERT(AesOpValid, !ctrl_err_storage_i |-> op_i inside {
+ AES_ENC,
+ AES_DEC
+ })
+ `ASSERT(AesCiphOpValid, !cipher_op_err |-> cipher_op_i inside {
+ CIPH_FWD,
+ CIPH_INV
+ })
`ASSERT(AesControlStateValid, !alert_o |-> aes_ctrl_cs inside {
IDLE,
LOAD,
diff --git a/hw/ip/aes/rtl/aes_control_fsm_n.sv b/hw/ip/aes/rtl/aes_control_fsm_n.sv
index 48db140..8e7fbf7 100644
--- a/hw/ip/aes/rtl/aes_control_fsm_n.sv
+++ b/hw/ip/aes/rtl/aes_control_fsm_n.sv
@@ -211,8 +211,8 @@
logic ctrl_err_storage;
aes_op_e op;
aes_mode_e mode;
- logic cipher_op_raw;
ciph_op_e cipher_op;
+ logic [$bits(cipher_op)-1:0] cipher_op_raw;
logic sideload;
prs_rate_e prng_reseed_rate;
logic manual_operation;
diff --git a/hw/ip/aes/rtl/aes_control_fsm_p.sv b/hw/ip/aes/rtl/aes_control_fsm_p.sv
index cff606f..3a93540 100644
--- a/hw/ip/aes/rtl/aes_control_fsm_p.sv
+++ b/hw/ip/aes/rtl/aes_control_fsm_p.sv
@@ -207,8 +207,8 @@
logic ctrl_err_storage;
aes_op_e op;
aes_mode_e mode;
- logic cipher_op_raw;
ciph_op_e cipher_op;
+ logic [$bits(cipher_op)-1:0] cipher_op_raw;
logic sideload;
prs_rate_e prng_reseed_rate;
logic manual_operation;
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index 624e2cf..671e0d4 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -872,7 +872,10 @@
AES_CTR,
AES_NONE
})
- `ASSERT_KNOWN(AesOpKnown, aes_op_q)
+ `ASSERT(AesOpValid, !ctrl_err_storage |-> aes_op_q inside {
+ AES_ENC,
+ AES_DEC
+ })
// Check parameters
`ASSERT_INIT(AesNumSlicesCtr, NumSlicesCtr == 8)
diff --git a/hw/ip/aes/rtl/aes_ctrl_reg_shadowed.sv b/hw/ip/aes/rtl/aes_ctrl_reg_shadowed.sv
index 9dafc81..700838b 100644
--- a/hw/ip/aes/rtl/aes_ctrl_reg_shadowed.sv
+++ b/hw/ip/aes/rtl/aes_ctrl_reg_shadowed.sv
@@ -45,6 +45,7 @@
// Signals
ctrl_reg_t ctrl_wd;
+ aes_op_e op;
aes_mode_e mode;
key_len_e key_len;
prs_rate_e prng_reseed_rate;
@@ -73,7 +74,14 @@
reg2hw_ctrl_i.force_zero_masks.qe;
// Get and resolve values from register interface.
- assign ctrl_wd.operation = aes_op_e'(reg2hw_ctrl_i.operation.q);
+ assign op = aes_op_e'(reg2hw_ctrl_i.operation.q);
+ always_comb begin : op_get
+ unique case (op)
+ AES_ENC: ctrl_wd.operation = AES_ENC;
+ AES_DEC: ctrl_wd.operation = AES_DEC;
+ default: ctrl_wd.operation = AES_ENC; // unsupported values are mapped to AES_ENC
+ endcase
+ end
assign mode = aes_mode_e'(reg2hw_ctrl_i.mode.q);
always_comb begin : mode_get
@@ -128,7 +136,7 @@
.rst_shadowed_ni,
.re (reg2hw_ctrl_i.operation.re),
.we (we_i),
- .wd (ctrl_wd.operation),
+ .wd ({ctrl_wd.operation}),
.de (1'b0),
.d ('0),
.qe (),
diff --git a/hw/ip/aes/rtl/aes_key_expand.sv b/hw/ip/aes/rtl/aes_key_expand.sv
index cb828e0..93ce733 100644
--- a/hw/ip/aes/rtl/aes_key_expand.sv
+++ b/hw/ip/aes/rtl/aes_key_expand.sv
@@ -447,7 +447,10 @@
SBoxImpl == SBoxImplCanright)))
// Selectors must be known/valid
- `ASSERT_KNOWN(AesCiphOpKnown, op_i)
+ `ASSERT(AesCiphOpValid, cfg_valid_i |-> op_i inside {
+ CIPH_FWD,
+ CIPH_INV
+ })
`ASSERT(AesKeyLenValid, cfg_valid_i |-> key_len_i inside {
AES_128,
AES_192,
diff --git a/hw/ip/aes/rtl/aes_mix_single_column.sv b/hw/ip/aes/rtl/aes_mix_single_column.sv
index acdc9c0..28e5346 100644
--- a/hw/ip/aes/rtl/aes_mix_single_column.sv
+++ b/hw/ip/aes/rtl/aes_mix_single_column.sv
@@ -56,8 +56,10 @@
assign z[1] = y2 ^ y[1];
// Mux z
- assign z_muxed[0] = (op_i == CIPH_FWD) ? 8'b0 : z[0];
- assign z_muxed[1] = (op_i == CIPH_FWD) ? 8'b0 : z[1];
+ assign z_muxed[0] = (op_i == CIPH_FWD) ? 8'b0 :
+ (op_i == CIPH_INV) ? z[0] : 8'b0;
+ assign z_muxed[1] = (op_i == CIPH_FWD) ? 8'b0 :
+ (op_i == CIPH_INV) ? z[1] : 8'b0;
// Drive outputs
assign data_o[0] = data_i[1] ^ x_mul2[3] ^ x[1] ^ z_muxed[1];
diff --git a/hw/ip/aes/rtl/aes_pkg.sv b/hw/ip/aes/rtl/aes_pkg.sv
index 0b9bb2c..a9c2b25 100644
--- a/hw/ip/aes/rtl/aes_pkg.sv
+++ b/hw/ip/aes/rtl/aes_pkg.sv
@@ -77,13 +77,14 @@
// Parameters used for controlgroups in the coverage
+parameter int AES_OP_WIDTH = 2;
parameter int AES_MODE_WIDTH = 6;
parameter int AES_KEYLEN_WIDTH = 3;
parameter int AES_PRNGRESEEDRATE_WIDTH = 3;
-typedef enum logic {
- AES_ENC = 1'b0,
- AES_DEC = 1'b1
+typedef enum logic [AES_OP_WIDTH-1:0] {
+ AES_ENC = 2'b01,
+ AES_DEC = 2'b10
} aes_op_e;
typedef enum logic [AES_MODE_WIDTH-1:0] {
@@ -95,9 +96,9 @@
AES_NONE = 6'b10_0000
} aes_mode_e;
-typedef enum logic {
- CIPH_FWD = 1'b0,
- CIPH_INV = 1'b1
+typedef enum logic [AES_OP_WIDTH-1:0] {
+ CIPH_FWD = 2'b01,
+ CIPH_INV = 2'b10
} ciph_op_e;
typedef enum logic [AES_KEYLEN_WIDTH-1:0] {
diff --git a/hw/ip/aes/rtl/aes_reg_pkg.sv b/hw/ip/aes/rtl/aes_reg_pkg.sv
index d09e07e..4eaddaf 100644
--- a/hw/ip/aes/rtl/aes_reg_pkg.sv
+++ b/hw/ip/aes/rtl/aes_reg_pkg.sv
@@ -57,7 +57,7 @@
typedef struct packed {
struct packed {
- logic q;
+ logic [1:0] q;
logic qe;
logic re;
} operation;
@@ -143,7 +143,7 @@
typedef struct packed {
struct packed {
- logic d;
+ logic [1:0] d;
} operation;
struct packed {
logic [5:0] d;
@@ -217,13 +217,13 @@
// Register -> HW type
typedef struct packed {
- aes_reg2hw_alert_test_reg_t alert_test; // [956:953]
- aes_reg2hw_key_share0_mreg_t [7:0] key_share0; // [952:689]
- aes_reg2hw_key_share1_mreg_t [7:0] key_share1; // [688:425]
- aes_reg2hw_iv_mreg_t [3:0] iv; // [424:293]
- aes_reg2hw_data_in_mreg_t [3:0] data_in; // [292:161]
- aes_reg2hw_data_out_mreg_t [3:0] data_out; // [160:29]
- aes_reg2hw_ctrl_shadowed_reg_t ctrl_shadowed; // [28:6]
+ aes_reg2hw_alert_test_reg_t alert_test; // [957:954]
+ aes_reg2hw_key_share0_mreg_t [7:0] key_share0; // [953:690]
+ aes_reg2hw_key_share1_mreg_t [7:0] key_share1; // [689:426]
+ aes_reg2hw_iv_mreg_t [3:0] iv; // [425:294]
+ aes_reg2hw_data_in_mreg_t [3:0] data_in; // [293:162]
+ aes_reg2hw_data_out_mreg_t [3:0] data_out; // [161:30]
+ aes_reg2hw_ctrl_shadowed_reg_t ctrl_shadowed; // [29:6]
aes_reg2hw_ctrl_aux_shadowed_reg_t ctrl_aux_shadowed; // [5:5]
aes_reg2hw_trigger_reg_t trigger; // [4:1]
aes_reg2hw_status_reg_t status; // [0:0]
@@ -231,12 +231,12 @@
// HW -> register type
typedef struct packed {
- aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [937:682]
- aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [681:426]
- aes_hw2reg_iv_mreg_t [3:0] iv; // [425:298]
- aes_hw2reg_data_in_mreg_t [3:0] data_in; // [297:166]
- aes_hw2reg_data_out_mreg_t [3:0] data_out; // [165:38]
- aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [37:22]
+ aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [938:683]
+ aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [682:427]
+ aes_hw2reg_iv_mreg_t [3:0] iv; // [426:299]
+ aes_hw2reg_data_in_mreg_t [3:0] data_in; // [298:167]
+ aes_hw2reg_data_out_mreg_t [3:0] data_out; // [166:39]
+ aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [38:22]
aes_hw2reg_trigger_reg_t trigger; // [21:14]
aes_hw2reg_status_reg_t status; // [13:0]
} aes_hw2reg_t;
@@ -329,8 +329,8 @@
parameter logic [31:0] AES_DATA_OUT_2_DATA_OUT_2_RESVAL = 32'h 0;
parameter logic [31:0] AES_DATA_OUT_3_RESVAL = 32'h 0;
parameter logic [31:0] AES_DATA_OUT_3_DATA_OUT_3_RESVAL = 32'h 0;
- parameter logic [15:0] AES_CTRL_SHADOWED_RESVAL = 16'h 8c0;
- parameter logic [0:0] AES_CTRL_SHADOWED_OPERATION_RESVAL = 1'h 0;
+ parameter logic [16:0] AES_CTRL_SHADOWED_RESVAL = 17'h 1181;
+ parameter logic [1:0] AES_CTRL_SHADOWED_OPERATION_RESVAL = 2'h 1;
parameter logic [5:0] AES_CTRL_SHADOWED_MODE_RESVAL = 6'h 20;
parameter logic [2:0] AES_CTRL_SHADOWED_KEY_LEN_RESVAL = 3'h 1;
parameter logic [0:0] AES_CTRL_SHADOWED_SIDELOAD_RESVAL = 1'h 0;
@@ -407,7 +407,7 @@
4'b 1111, // index[26] AES_DATA_OUT_1
4'b 1111, // index[27] AES_DATA_OUT_2
4'b 1111, // index[28] AES_DATA_OUT_3
- 4'b 0011, // index[29] AES_CTRL_SHADOWED
+ 4'b 0111, // index[29] AES_CTRL_SHADOWED
4'b 0001, // index[30] AES_CTRL_AUX_SHADOWED
4'b 0001, // index[31] AES_CTRL_AUX_REGWEN
4'b 0001, // index[32] AES_TRIGGER
diff --git a/hw/ip/aes/rtl/aes_reg_top.sv b/hw/ip/aes/rtl/aes_reg_top.sv
index 4e30344..7f048c8 100644
--- a/hw/ip/aes/rtl/aes_reg_top.sv
+++ b/hw/ip/aes/rtl/aes_reg_top.sv
@@ -170,8 +170,8 @@
logic [31:0] data_out_3_qs;
logic ctrl_shadowed_re;
logic ctrl_shadowed_we;
- logic ctrl_shadowed_operation_qs;
- logic ctrl_shadowed_operation_wd;
+ logic [1:0] ctrl_shadowed_operation_qs;
+ logic [1:0] ctrl_shadowed_operation_wd;
logic [5:0] ctrl_shadowed_mode_qs;
logic [5:0] ctrl_shadowed_mode_wd;
logic [2:0] ctrl_shadowed_key_len_qs;
@@ -728,9 +728,9 @@
// R[ctrl_shadowed]: V(True)
- // F[operation]: 0:0
+ // F[operation]: 1:0
prim_subreg_ext #(
- .DW (1)
+ .DW (2)
) u_ctrl_shadowed_operation (
.re (ctrl_shadowed_re),
.we (ctrl_shadowed_we),
@@ -742,7 +742,7 @@
.qs (ctrl_shadowed_operation_qs)
);
- // F[mode]: 6:1
+ // F[mode]: 7:2
prim_subreg_ext #(
.DW (6)
) u_ctrl_shadowed_mode (
@@ -756,7 +756,7 @@
.qs (ctrl_shadowed_mode_qs)
);
- // F[key_len]: 9:7
+ // F[key_len]: 10:8
prim_subreg_ext #(
.DW (3)
) u_ctrl_shadowed_key_len (
@@ -770,7 +770,7 @@
.qs (ctrl_shadowed_key_len_qs)
);
- // F[sideload]: 10:10
+ // F[sideload]: 11:11
prim_subreg_ext #(
.DW (1)
) u_ctrl_shadowed_sideload (
@@ -784,7 +784,7 @@
.qs (ctrl_shadowed_sideload_qs)
);
- // F[prng_reseed_rate]: 13:11
+ // F[prng_reseed_rate]: 14:12
prim_subreg_ext #(
.DW (3)
) u_ctrl_shadowed_prng_reseed_rate (
@@ -798,7 +798,7 @@
.qs (ctrl_shadowed_prng_reseed_rate_qs)
);
- // F[manual_operation]: 14:14
+ // F[manual_operation]: 15:15
prim_subreg_ext #(
.DW (1)
) u_ctrl_shadowed_manual_operation (
@@ -812,7 +812,7 @@
.qs (ctrl_shadowed_manual_operation_qs)
);
- // F[force_zero_masks]: 15:15
+ // F[force_zero_masks]: 16:16
prim_subreg_ext #(
.DW (1)
) u_ctrl_shadowed_force_zero_masks (
@@ -1328,19 +1328,19 @@
assign ctrl_shadowed_re = addr_hit[29] & reg_re & !reg_error;
assign ctrl_shadowed_we = addr_hit[29] & reg_we & !reg_error;
- assign ctrl_shadowed_operation_wd = reg_wdata[0];
+ assign ctrl_shadowed_operation_wd = reg_wdata[1:0];
- assign ctrl_shadowed_mode_wd = reg_wdata[6:1];
+ assign ctrl_shadowed_mode_wd = reg_wdata[7:2];
- assign ctrl_shadowed_key_len_wd = reg_wdata[9:7];
+ assign ctrl_shadowed_key_len_wd = reg_wdata[10:8];
- assign ctrl_shadowed_sideload_wd = reg_wdata[10];
+ assign ctrl_shadowed_sideload_wd = reg_wdata[11];
- assign ctrl_shadowed_prng_reseed_rate_wd = reg_wdata[13:11];
+ assign ctrl_shadowed_prng_reseed_rate_wd = reg_wdata[14:12];
- assign ctrl_shadowed_manual_operation_wd = reg_wdata[14];
+ assign ctrl_shadowed_manual_operation_wd = reg_wdata[15];
- assign ctrl_shadowed_force_zero_masks_wd = reg_wdata[15];
+ assign ctrl_shadowed_force_zero_masks_wd = reg_wdata[16];
assign ctrl_aux_shadowed_re = addr_hit[30] & reg_re & !reg_error;
assign ctrl_aux_shadowed_we = addr_hit[30] & reg_we & !reg_error;
@@ -1480,13 +1480,13 @@
end
addr_hit[29]: begin
- reg_rdata_next[0] = ctrl_shadowed_operation_qs;
- reg_rdata_next[6:1] = ctrl_shadowed_mode_qs;
- reg_rdata_next[9:7] = ctrl_shadowed_key_len_qs;
- reg_rdata_next[10] = ctrl_shadowed_sideload_qs;
- reg_rdata_next[13:11] = ctrl_shadowed_prng_reseed_rate_qs;
- reg_rdata_next[14] = ctrl_shadowed_manual_operation_qs;
- reg_rdata_next[15] = ctrl_shadowed_force_zero_masks_qs;
+ reg_rdata_next[1:0] = ctrl_shadowed_operation_qs;
+ reg_rdata_next[7:2] = ctrl_shadowed_mode_qs;
+ reg_rdata_next[10:8] = ctrl_shadowed_key_len_qs;
+ reg_rdata_next[11] = ctrl_shadowed_sideload_qs;
+ reg_rdata_next[14:12] = ctrl_shadowed_prng_reseed_rate_qs;
+ reg_rdata_next[15] = ctrl_shadowed_manual_operation_qs;
+ reg_rdata_next[16] = ctrl_shadowed_force_zero_masks_qs;
end
addr_hit[30]: begin
diff --git a/hw/ip/aes/rtl/aes_sbox_canright.sv b/hw/ip/aes/rtl/aes_sbox_canright.sv
index ff4da73..4d7432d 100644
--- a/hw/ip/aes/rtl/aes_sbox_canright.sv
+++ b/hw/ip/aes/rtl/aes_sbox_canright.sv
@@ -55,14 +55,16 @@
logic [7:0] data_basis_x, data_inverse;
// Convert to normal basis X.
- assign data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
- aes_mvm(data_i ^ 8'h63, S2X);
+ assign data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
+ (op_i == CIPH_INV) ? aes_mvm(data_i ^ 8'h63, S2X) :
+ aes_mvm(data_i, A2X);
// Do the inversion in normal basis X.
assign data_inverse = aes_inverse_gf2p8(data_basis_x);
// Convert to basis S or A.
assign data_o = (op_i == CIPH_FWD) ? aes_mvm(data_inverse, X2S) ^ 8'h63 :
- aes_mvm(data_inverse, X2A);
+ (op_i == CIPH_INV) ? aes_mvm(data_inverse, X2A) :
+ aes_mvm(data_inverse, X2S) ^ 8'h63;
endmodule
diff --git a/hw/ip/aes/rtl/aes_sbox_canright_masked.sv b/hw/ip/aes/rtl/aes_sbox_canright_masked.sv
index db93d14..b537068 100644
--- a/hw/ip/aes/rtl/aes_sbox_canright_masked.sv
+++ b/hw/ip/aes/rtl/aes_sbox_canright_masked.sv
@@ -450,8 +450,9 @@
logic [7:0] in_mask_basis_x, out_mask_basis_x;
// Convert data to normal basis X.
- assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
- aes_mvm(data_i ^ 8'h63, S2X);
+ assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
+ (op_i == CIPH_INV) ? aes_mvm(data_i ^ 8'h63, S2X) :
+ aes_mvm(data_i, A2X);
// For the masked Canright SBox, the output mask directly corresponds to the pseduo-random data
// provided as input.
@@ -460,10 +461,12 @@
// Convert masks to normal basis X.
// The addition of constant 8'h63 following the affine transformation is skipped.
assign in_mask_basis_x = (op_i == CIPH_FWD) ? aes_mvm(mask_i, A2X) :
- aes_mvm(mask_i, S2X);
+ (op_i == CIPH_INV) ? aes_mvm(mask_i, S2X) :
+ aes_mvm(mask_i, A2X);
// The output mask is converted in the opposite direction.
assign out_mask_basis_x = (op_i == CIPH_INV) ? aes_mvm(mask_o, A2X) :
+ (op_i == CIPH_FWD) ? aes_mvm(mask_o, S2X) :
aes_mvm(mask_o, S2X);
// Do the inversion in normal basis X.
@@ -476,6 +479,7 @@
// Convert to basis S or A.
assign data_o = (op_i == CIPH_FWD) ? (aes_mvm(out_data_basis_x, X2S) ^ 8'h63) :
- (aes_mvm(out_data_basis_x, X2A));
+ (op_i == CIPH_INV) ? (aes_mvm(out_data_basis_x, X2A)) :
+ (aes_mvm(out_data_basis_x, X2S) ^ 8'h63);
endmodule
diff --git a/hw/ip/aes/rtl/aes_sbox_canright_masked_noreuse.sv b/hw/ip/aes/rtl/aes_sbox_canright_masked_noreuse.sv
index 20b2f02..c7577b4 100644
--- a/hw/ip/aes/rtl/aes_sbox_canright_masked_noreuse.sv
+++ b/hw/ip/aes/rtl/aes_sbox_canright_masked_noreuse.sv
@@ -409,8 +409,9 @@
logic [7:0] in_mask_basis_x, out_mask_basis_x;
// Convert data to normal basis X.
- assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
- aes_mvm(data_i ^ 8'h63, S2X);
+ assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
+ (op_i == CIPH_INV) ? aes_mvm(data_i ^ 8'h63, S2X) :
+ aes_mvm(data_i, A2X);
// For the masked Canright SBox with no re-use, the output mask directly corresponds to the
// LSBs of the pseduo-random data provided as input.
@@ -423,10 +424,12 @@
// Convert masks to normal basis X.
// The addition of constant 8'h63 following the affine transformation is skipped.
assign in_mask_basis_x = (op_i == CIPH_FWD) ? aes_mvm(mask_i, A2X) :
- aes_mvm(mask_i, S2X);
+ (op_i == CIPH_INV) ? aes_mvm(mask_i, S2X) :
+ aes_mvm(mask_i, A2X);
// The output mask is converted in the opposite direction.
assign out_mask_basis_x = (op_i == CIPH_INV) ? aes_mvm(mask_o, A2X) :
+ (op_i == CIPH_FWD) ? aes_mvm(mask_o, S2X) :
aes_mvm(mask_o, S2X);
// Do the inversion in normal basis X.
@@ -440,6 +443,7 @@
// Convert to basis S or A.
assign data_o = (op_i == CIPH_FWD) ? (aes_mvm(out_data_basis_x, X2S) ^ 8'h63) :
- (aes_mvm(out_data_basis_x, X2A));
+ (op_i == CIPH_INV) ? (aes_mvm(out_data_basis_x, X2A)) :
+ (aes_mvm(out_data_basis_x, X2S) ^ 8'h63);
endmodule
diff --git a/hw/ip/aes/rtl/aes_sbox_dom.sv b/hw/ip/aes/rtl/aes_sbox_dom.sv
index 6dfdde4..ef4bf68 100644
--- a/hw/ip/aes/rtl/aes_sbox_dom.sv
+++ b/hw/ip/aes/rtl/aes_sbox_dom.sv
@@ -1010,13 +1010,15 @@
prd_out_t out_prd;
// Convert data to normal basis X.
- assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
- aes_mvm(data_i ^ 8'h63, S2X);
+ assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) :
+ (op_i == CIPH_INV) ? aes_mvm(data_i ^ 8'h63, S2X) :
+ aes_mvm(data_i, A2X);
// Convert mask to normal basis X.
// The addition of constant 8'h63 prior to the affine transformation is skipped.
- assign in_mask_basis_x = (op_i == CIPH_FWD) ? aes_mvm(mask_i, A2X) :
- aes_mvm(mask_i, S2X);
+ assign in_mask_basis_x = (op_i == CIPH_FWD) ? aes_mvm(mask_i, A2X) :
+ (op_i == CIPH_INV) ? aes_mvm(mask_i, S2X) :
+ aes_mvm(mask_i, A2X);
// Do the inversion in normal basis X.
aes_dom_inverse_gf2p8 #(
@@ -1035,12 +1037,14 @@
// Convert data to basis S or A.
assign data_o = (op_i == CIPH_FWD) ? (aes_mvm(out_data_basis_x, X2S) ^ 8'h63) :
- (aes_mvm(out_data_basis_x, X2A));
+ (op_i == CIPH_INV) ? (aes_mvm(out_data_basis_x, X2A)) :
+ (aes_mvm(out_data_basis_x, X2S) ^ 8'h63);
// Convert mask to basis S or A.
// The addition of constant 8'h63 following the affine transformation is skipped.
assign mask_o = (op_i == CIPH_FWD) ? aes_mvm(out_mask_basis_x, X2S) :
- aes_mvm(out_mask_basis_x, X2A);
+ (op_i == CIPH_INV) ? aes_mvm(out_mask_basis_x, X2A) :
+ aes_mvm(out_mask_basis_x, X2S);
// Counter register
logic [2:0] count_d, count_q;
diff --git a/hw/ip/aes/rtl/aes_sbox_lut.sv b/hw/ip/aes/rtl/aes_sbox_lut.sv
index 3eb9507..e57b910 100644
--- a/hw/ip/aes/rtl/aes_sbox_lut.sv
+++ b/hw/ip/aes/rtl/aes_sbox_lut.sv
@@ -114,6 +114,7 @@
};
// Drive output
- assign data_o = (op_i == CIPH_FWD) ? SBOX_FWD[data_i] : SBOX_INV[data_i];
+ assign data_o = (op_i == CIPH_FWD) ? SBOX_FWD[data_i] :
+ (op_i == CIPH_INV) ? SBOX_INV[data_i] : SBOX_FWD[data_i];
endmodule
diff --git a/hw/ip/aes/rtl/aes_shift_rows.sv b/hw/ip/aes/rtl/aes_shift_rows.sv
index b33b570..e5a62e9 100644
--- a/hw/ip/aes/rtl/aes_shift_rows.sv
+++ b/hw/ip/aes/rtl/aes_shift_rows.sv
@@ -19,11 +19,13 @@
assign data_o[2] = aes_circ_byte_shift(data_i[2], 2'h2);
// Row 1
- assign data_o[1] = (op_i == CIPH_FWD) ? aes_circ_byte_shift(data_i[1], 2'h3)
- : aes_circ_byte_shift(data_i[1], 2'h1);
+ assign data_o[1] = (op_i == CIPH_FWD) ? aes_circ_byte_shift(data_i[1], 2'h3) :
+ (op_i == CIPH_INV) ? aes_circ_byte_shift(data_i[1], 2'h1) :
+ aes_circ_byte_shift(data_i[1], 2'h3);
// Row 3
- assign data_o[3] = (op_i == CIPH_FWD) ? aes_circ_byte_shift(data_i[3], 2'h1)
- : aes_circ_byte_shift(data_i[3], 2'h3);
+ assign data_o[3] = (op_i == CIPH_FWD) ? aes_circ_byte_shift(data_i[3], 2'h1) :
+ (op_i == CIPH_INV) ? aes_circ_byte_shift(data_i[3], 2'h3) :
+ aes_circ_byte_shift(data_i[3], 2'h1);
endmodule
diff --git a/hw/ip/aes/rtl/aes_wrap.sv b/hw/ip/aes/rtl/aes_wrap.sv
index 348f584..dfe4029 100644
--- a/hw/ip/aes/rtl/aes_wrap.sv
+++ b/hw/ip/aes/rtl/aes_wrap.sv
@@ -194,7 +194,7 @@
h2d.a_valid = 1'b1;
h2d.a_opcode = PutFullData;
h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_CTRL_SHADOWED_OFFSET};
- h2d.a_data = {19'h0, 1'b0 ,1'b0, SIDELOAD, AES_128, AES_MODE, AES_ENC};
+ h2d.a_data = {18'h0, 1'b0 ,1'b0, SIDELOAD, AES_128, AES_MODE, AES_ENC};
// We can't do back to back transactions. De-assert valid while receiving response.
if (d2h.d_valid) begin
diff --git a/sw/device/lib/dif/dif_aes.c b/sw/device/lib/dif/dif_aes.c
index fc2b519..8666cc8 100644
--- a/sw/device/lib/dif/dif_aes.c
+++ b/sw/device/lib/dif/dif_aes.c
@@ -17,6 +17,18 @@
*/
/*
+ * Field to select AES operation.
+ *
+ * Invalid input values, i.e., value with multiple bits set - are mapped to
+ * `kAesOperationFieldValEnc`.
+ */
+typedef enum aes_operation_field_val {
+ kAesOperationFieldValInvalid = 0x0,
+ kAesOperationFieldValEnc = 0x1, /**< Enrcyption. */
+ kAesOperationFieldValDec = 0x2, /**< Decryption. */
+} aes_operation_field_val_t;
+
+/*
* Field to select AES block cipher mode.
*
* Invalid input values, i.e., value with multiple bits set - are mapped to
@@ -111,6 +123,38 @@
}
}
+static aes_operation_field_val_t operation_to_field(
+ dif_aes_operation_t operation) {
+ switch (operation) {
+ case kDifAesOperationEncrypt:
+ return kAesOperationFieldValEnc;
+ case kDifAesOperationDecrypt:
+ return kAesOperationFieldValDec;
+ default:
+ return kAesOperationFieldValInvalid;
+ }
+}
+
+// TODO: We should extract the MODE from the transaction using this function and
+// not separately provide it. See
+// https://github.com/lowRISC/opentitan/issues/10487
+// static aes_mode_field_val_t mode_to_field(dif_aes_mode_t mode) {
+// switch (mode) {
+// case kDifAesModeEcb:
+// return kAesModeFieldValEcb;
+// case kDifAesModeCbc:
+// return kAesModeFieldValCbc;
+// case kDifAesModeCfb:
+// return kAesModeFieldValCfb;
+// case kDifAesModeOfb:
+// return kAesModeFieldValOfb;
+// case kDifAesModeCtr:
+// return kAesModeFieldValCtr;
+// default:
+// return kAesModeFieldValNone;
+// }
+//}
+
static aes_key_field_val_t key_to_field(dif_aes_key_length_t key) {
switch (key) {
case kDifAesKey128:
@@ -129,30 +173,37 @@
*
* @param aes AES state data.
* @param transaction Configuration data, common across all Cipher modes.
- * @param cipher_mode_val Cipher Mode register write value.
+ * @param mode_val Block cipher mode of operation register write value.
* @return `dif_result_t`.
*/
static dif_result_t configure(const dif_aes_t *aes,
const dif_aes_transaction_t *transaction,
- aes_mode_field_val_t cipher_mode_val) {
+ aes_mode_field_val_t mode_val) {
+ aes_operation_field_val_t operation_val =
+ operation_to_field(transaction->operation);
+ if (operation_val == kAesOperationFieldValInvalid) {
+ return kDifError;
+ }
+ // TODO: We should extract the mode from the transaction and not separately
+ // provide it. See https://github.com/lowRISC/opentitan/issues/10487
+ // aes_mode_field_val_t mode_val = mode_to_field(transaction->mode);
+ // if (mode_val == kAesModeFieldValNone) {
+ // return kDifError;
+ //}
aes_key_field_val_t key_len_val = key_to_field(transaction->key_len);
if (key_len_val == kAesKeyFieldValInvalid) {
return kDifError;
}
- uint32_t reg =
- bitfield_field32_write(0, AES_CTRL_SHADOWED_KEY_LEN_FIELD, key_len_val);
+ uint32_t reg = bitfield_field32_write(0, AES_CTRL_SHADOWED_OPERATION_FIELD,
+ operation_val);
- reg = bitfield_field32_write(reg, AES_CTRL_SHADOWED_MODE_FIELD,
- cipher_mode_val);
+ reg = bitfield_field32_write(reg, AES_CTRL_SHADOWED_MODE_FIELD, mode_val);
- if (transaction->mode == kDifAesModeDecrypt) {
- reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_OPERATION_BIT, true);
- } else {
- reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_OPERATION_BIT, false);
- }
+ reg =
+ bitfield_field32_write(reg, AES_CTRL_SHADOWED_KEY_LEN_FIELD, key_len_val);
- if (transaction->operation == kDifAesOperationManual) {
+ if (transaction->manual_operation == kDifAesManualOperationManual) {
reg =
bitfield_bit32_write(reg, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
} else {
@@ -197,16 +248,18 @@
aes_clear_internal_state(aes);
- uint32_t reg =
- bitfield_bit32_write(0, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
-
// Any values would do, illegal values chosen here.
+ uint32_t reg =
+ bitfield_field32_write(0, AES_CTRL_SHADOWED_OPERATION_FIELD, 0xffffffff);
+
reg = bitfield_field32_write(reg, AES_CTRL_SHADOWED_MODE_FIELD,
AES_CTRL_SHADOWED_MODE_VALUE_AES_NONE);
reg =
bitfield_field32_write(reg, AES_CTRL_SHADOWED_KEY_LEN_FIELD, 0xffffffff);
+ reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
+
aes_shadowed_write(aes->base_addr, AES_CTRL_SHADOWED_REG_OFFSET, reg);
return kDifOk;
diff --git a/sw/device/lib/dif/dif_aes.h b/sw/device/lib/dif/dif_aes.h
index 65e767c..f75a7ce 100644
--- a/sw/device/lib/dif/dif_aes.h
+++ b/sw/device/lib/dif/dif_aes.h
@@ -82,6 +82,46 @@
} dif_aes_data_t;
/**
+ * AES operation.
+ */
+typedef enum dif_aes_operation {
+ /**
+ * AES encryption.
+ */
+ kDifAesOperationEncrypt = 0,
+ /**
+ * AES decryption.
+ */
+ kDifAesOperationDecrypt,
+} dif_aes_operation_t;
+
+/**
+ * AES block cipher mode of operation.
+ */
+typedef enum dif_aes_mode {
+ /**
+ * The Electronic Codebook Mode.
+ */
+ kDifAesModeEcb = 0,
+ /**
+ * The Cipher Block Chaining Mode.
+ */
+ kDifAesModeCbc,
+ /**
+ * The Cipher Feedback Mode.
+ */
+ kDifAesModeCfb,
+ /**
+ * The Output Feedback Mode.
+ */
+ kDifAesModeOfb,
+ /**
+ * The Counter Mode.
+ */
+ kDifAesModeCtr,
+} dif_aes_mode_t;
+
+/**
* AES key length in bits.
*/
typedef enum dif_aes_key_length {
@@ -100,34 +140,20 @@
} dif_aes_key_length_t;
/**
- * AES mode.
+ * AES manual operation.
*/
-typedef enum dif_aes_mode {
- /**
- * AES encryption mode.
- */
- kDifAesModeEncrypt = 0,
- /**
- * AES decryption mode.
- */
- kDifAesModeDecrypt,
-} dif_aes_mode_t;
-
-/**
- * AES operation.
- */
-typedef enum dif_aes_operation {
+typedef enum dif_aes_manual_operation {
/**
* AES operates in automatic mode - which means that the encryption/decryption
* is automatically triggered on every successful `dif_aes_*_load_data()`.
*/
- kDifAesOperationAuto = 0,
+ kDifAesManualOperationAuto = 0,
/**
* AES operates in manual mode - which means that the encryption/decryption
* is manually triggered by `dif_aes_trigger(kDifAesTriggerStart)`.
*/
- kDifAesOperationManual,
-} dif_aes_operation_t;
+ kDifAesManualOperationManual,
+} dif_aes_manual_operation_t;
/**
* AES masking.
@@ -151,9 +177,10 @@
* Parameters for an AES transaction.
*/
typedef struct dif_aes_transaction {
- dif_aes_key_length_t key_len;
- dif_aes_mode_t mode;
dif_aes_operation_t operation;
+ dif_aes_mode_t mode;
+ dif_aes_key_length_t key_len;
+ dif_aes_manual_operation_t manual_operation;
dif_aes_masking_t masking;
} dif_aes_transaction_t;
diff --git a/sw/device/lib/dif/dif_aes_unittest.cc b/sw/device/lib/dif/dif_aes_unittest.cc
index 5b3a7ec..0c13bd2 100644
--- a/sw/device/lib/dif/dif_aes_unittest.cc
+++ b/sw/device/lib/dif/dif_aes_unittest.cc
@@ -60,9 +60,10 @@
dif_aes_t aes_;
const dif_aes_transaction_t kTransaction = {
+ .operation = kDifAesOperationEncrypt,
+ .mode = kDifAesModeEcb,
.key_len = kDifAesKey128,
- .mode = kDifAesModeEncrypt,
- .operation = kDifAesOperationAuto,
+ .manual_operation = kDifAesManualOperationAuto,
.masking = kDifAesMaskingInternalPrng,
};
@@ -86,7 +87,7 @@
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, 0x01},
{AES_CTRL_SHADOWED_MODE_OFFSET, 0x01},
- {AES_CTRL_SHADOWED_OPERATION_BIT, false},
+ {AES_CTRL_SHADOWED_OPERATION_OFFSET, 0x1},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
@@ -105,7 +106,7 @@
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, 0x01},
{AES_CTRL_SHADOWED_MODE_OFFSET, 0x02},
- {AES_CTRL_SHADOWED_OPERATION_BIT, false},
+ {AES_CTRL_SHADOWED_OPERATION_OFFSET, 0x1},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
@@ -125,7 +126,7 @@
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, 0x01},
{AES_CTRL_SHADOWED_MODE_OFFSET, 0x04},
- {AES_CTRL_SHADOWED_OPERATION_BIT, false},
+ {AES_CTRL_SHADOWED_OPERATION_OFFSET, 0x1},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
@@ -145,7 +146,7 @@
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, 0x01},
{AES_CTRL_SHADOWED_MODE_OFFSET, 0x08},
- {AES_CTRL_SHADOWED_OPERATION_BIT, false},
+ {AES_CTRL_SHADOWED_OPERATION_OFFSET, 0x1},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
@@ -165,7 +166,7 @@
EXPECT_WRITE32(AES_CTRL_SHADOWED_REG_OFFSET,
{{AES_CTRL_SHADOWED_KEY_LEN_OFFSET, 0x01},
{AES_CTRL_SHADOWED_MODE_OFFSET, 0x10},
- {AES_CTRL_SHADOWED_OPERATION_BIT, false},
+ {AES_CTRL_SHADOWED_OPERATION_OFFSET, 0x1},
{AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, false},
{AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, false}});
}
diff --git a/sw/device/sca/aes_serial.c b/sw/device/sca/aes_serial.c
index 5dc1286..a4d57e1 100644
--- a/sw/device/sca/aes_serial.c
+++ b/sw/device/sca/aes_serial.c
@@ -54,10 +54,11 @@
static void aes_serial_set_key(const uint8_t *key, size_t key_len) {
SS_CHECK(key_len == kAesKeyLength);
dif_aes_transaction_t transaction = {
+ .operation = kDifAesOperationEncrypt,
+ .mode = kDifAesModeEcb,
.key_len = kDifAesKey128,
.masking = kDifAesMaskingInternalPrng,
- .mode = kDifAesModeEncrypt,
- .operation = kDifAesOperationManual,
+ .manual_operation = kDifAesManualOperationManual,
};
dif_aes_key_share_t key_shares;
memcpy(key_shares.share0, key, sizeof(key_shares.share0));
diff --git a/sw/device/tests/aes_smoketest.c b/sw/device/tests/aes_smoketest.c
index ab6596f..26c7a27 100644
--- a/sw/device/tests/aes_smoketest.c
+++ b/sw/device/tests/aes_smoketest.c
@@ -88,9 +88,10 @@
// Setup ECB encryption transaction.
dif_aes_transaction_t transaction = {
+ .operation = kDifAesOperationEncrypt,
+ .mode = kDifAesModeEcb,
.key_len = kDifAesKey256,
- .mode = kDifAesModeEncrypt,
- .operation = kDifAesOperationAuto,
+ .manual_operation = kDifAesManualOperationAuto,
};
CHECK_DIF_OK(dif_aes_start_ecb(&aes, &transaction, key));
@@ -122,7 +123,7 @@
}
// Setup ECB decryption transaction.
- transaction.mode = kDifAesModeDecrypt;
+ transaction.operation = kDifAesOperationDecrypt;
CHECK_DIF_OK(dif_aes_start_ecb(&aes, &transaction, key));
// Load the previously produced cipher text to start the decryption operation.