[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.