Skip to content

Commit

Permalink
[aes] Extend CSRs for AES-GCM support
Browse files Browse the repository at this point in the history
Signed-off-by: Pirmin Vogel <[email protected]>
  • Loading branch information
vogelpi committed Oct 14, 2024
1 parent fe3c200 commit 08509c5
Show file tree
Hide file tree
Showing 13 changed files with 547 additions and 44 deletions.
1 change: 1 addition & 0 deletions hw/ip/aes/aes.core
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ filesets:
- rtl/aes_pkg.sv
- rtl/aes_reg_top.sv
- rtl/aes_ctrl_reg_shadowed.sv
- rtl/aes_ctrl_gcm_reg_shadowed.sv
- rtl/aes_core.sv
- rtl/aes_ctr.sv
- rtl/aes_ctr_fsm.sv
Expand Down
124 changes: 121 additions & 3 deletions hw/ip/aes/data/aes.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -635,11 +635,11 @@
}
{ bits: "7:2",
name: "MODE",
resval: "0x20",
resval: "0x3f",
hwaccess: "hrw",
desc: '''
6-bit one-hot field to select AES block cipher mode.
Invalid input values, i.e., values with multiple bits set and value 6'b00_0000, are mapped to AES_NONE (6'b10_0000).
Invalid input values, i.e., values with multiple bits set and value 6'b00_0000, are mapped to AES_NONE (6'b11_1111).
'''
enum: [
{ value: "1",
Expand Down Expand Up @@ -673,9 +673,16 @@
'''
},
{ value: "32",
name: "AES_GCM",
desc: '''
6'b10_0000: Galois/Counter Mode (GCM).
In case support for GCM has been disabled at compile time, setting this value results in configuring AES_NONE (6'b11_1111).
'''
},
{ value: "63",
name: "AES_NONE",
desc: '''
6'b10_0000: Invalid input values, i.e., value with multiple bits set and value 6'b00_0000, are mapped to AES_NONE.
6'b11_1111: Invalid input values, i.e., value with multiple bits set, value 6'b00_0000, and value 6'b10_0000 in case GCM is not supported (because disabled at compile time) are mapped to AES_NONE.
'''
}
]
Expand Down Expand Up @@ -970,5 +977,116 @@
}
]
},
{ name: "CTRL_GCM_SHADOWED",
desc: '''
Galois/Counter Mode (GCM) Control Register.

Can only be updated when the AES unit is idle.
If the AES unit is non-idle, writes to this register are ignored.
This register is shadowed, meaning two subsequent write operations are required to change its content.
If the two write operations try to set a different value, a recoverable alert is triggered (See Status Register).
A read operation clears the internal phase tracking: The next write operation is always considered a first write operation of an update sequence.
'''
swaccess: "rw",
hwaccess: "hrw",
hwext: "true",
hwqe: "true",
shadowed: "true",
update_err_alert: "recov_ctrl_update_err",
storage_err_alert: "fatal_fault",
fields: [
{ bits: "6:0",
name: "PHASE",
resval: "0x01",
hwaccess: "hrw",
desc: '''
7-bit one-hot field to select the phase of the Galois/Counter Mode (GCM) of operation.
Invalid input values, i.e., values with multiple bits set and value 7'b000_0000, are mapped to GCM_INIT (7'b000_0001).
In case support for GCM has been disabled at compile time, this field is not writable and always reads as GCM_INIT (7'b000_0001).
'''
enum: [
{ value: "1",
name: "GCM_INIT",
desc: '''
7'b000_0001: Initialization phase.
Software configures the Initial Key and IV Registers.
The hardware then generates the hash subkey and loads it into the internal GHASH block.
Once the AES unit is idle again, software can advance to the next phase.
Possible next phases are GCM_RESTORE, GCM_AAD and GCM_TEXT.
Invalid input values, i.e., values with multiple bits set, value 7'b000_0000, and all other values in case GCM is not supported (because disabled at compile time) are mapped to GCM_INIT.
'''
},
{ value: "2",
name: "GCM_RESTORE",
desc: '''
7'b000_0010: Optional context restore phase.
Software configures the IV and Input Data Registers to restore a previously saved AES-GCM context (IV and GHASH state).
Possible next phases are GCM_INIT, GCM_AAD and GCM_TEXT.
'''
},
{ value: "4",
name: "GCM_AAD",
desc: '''
7'b000_0100: Optional additional authenticated data phase (AAD).
Software inputs the AAD via Input Data Registers block by block via Input Data Registers.
Possible next phases are GCM_INIT, GCM_TEXT, GCM_SAVE and GCM_LEN.
'''
},
{ value: "8",
name: "GCM_TEXT",
desc: '''
7'b000_1000: Optional plaintext/ciphertext phase.
Software inputs the plaintext/ciphertext block by block via Input Data Registers, and retrieves the output ciphertext/plaintext block by block via Output Data Registers.
Possible next phases are GCM_INIT, GCM_SAVE and GCM_LEN.
'''
},
{ value: "16",
name: "GCM_SAVE",
desc: '''
7'b001_0000: Optional context save phase.
The hardware stops accepting inputs.
Software reads the current GHASH state and IV via Output Data and IV Registers, respectively.
The only possible next phase is GCM_INIT.
'''
},
{ value: "32",
name: "GCM_LEN",
desc: '''
7'b010_0000: Length phase.
Software inputs a single data block containing the length of the AAD and the ciphertext via Input Data Registers.
Once the AES unit is idle again, software reads the GHASH output via Output Data Registers and then advances to the next phase.
Possible next phase are GCM_INIT and GCM_TAG.
'''
},
{ value: "64",
name: "GCM_TAG",
desc: '''
7'b100_0000: Tag phase.
Software inputs again the original IV via IV Registers and the previously read GHASH output via Input Data Registers.
Once the AES unit is idle again, software reads the final integrity tag via Data Out Registers.
The only possible next phase is GCM_INIT.
'''
}
]
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_gcm_reg_shadowed.u_ctrl_gcm_reg_shadowed_phase"]
}
{ bits: "12:8",
name: "NUM_VALID_BYTES",
resval: "16",
hwaccess: "hrw",
desc: '''
Number of valid bytes of the current input block.
Only the last block in the GCM_AAD and GCM_TEXT phases are expected to have not all bytes marked as valid.
For all other blocks, the number of valid bytes should be set to 16.
Invalid input values, i.e., the value 5'b0_0000, and all other values different from 5'b1_0000 in case GCM is not supported (because disabled at compile time) are mapped to 5'b1_0000.
'''
tags: ["shadowed_reg_path:u_aes_core.u_ctrl_gcm_reg_shadowed.u_ctrl_gcm_reg_shadowed_num_valid_bytes"]
}
]
tags: [// Updated by the HW.
// Updates based on writes to this reg (reset test possible).
// Exclude from write-read checks.
"excl:CsrNonInitTests:CsrExclWriteCheck"]
},
],
}
2 changes: 2 additions & 0 deletions hw/ip/aes/rtl/aes.sv
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module aes
import aes_reg_pkg::*;
#(
parameter bit AES192Enable = 1, // Can be 0 (disable), or 1 (enable).
parameter bit AESGCMEnable = 1, // Can be 0 (disable), or 1 (enable).
parameter bit SecMasking = 1, // Can be 0 (no masking), or
// 1 (first-order masking) of the cipher
// core. Masking requires the use of a
Expand Down Expand Up @@ -174,6 +175,7 @@ module aes
// AES core
aes_core #(
.AES192Enable ( AES192Enable ),
.AESGCMEnable ( AESGCMEnable ),
.SecMasking ( SecMasking ),
.SecSBoxImpl ( SecSBoxImpl ),
.SecStartTriggerDelay ( SecStartTriggerDelay ),
Expand Down
11 changes: 11 additions & 0 deletions hw/ip/aes/rtl/aes_control.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ module aes_control
input prs_rate_e prng_reseed_rate_i,
input logic manual_operation_i,
input logic key_touch_forces_reseed_i,
input logic ctrl_gcm_qe_i,
output logic ctrl_gcm_we_o,
input gcm_phase_e gcm_phase_i,
input logic start_i,
input logic key_iv_data_in_clear_i,
input logic data_out_clear_i,
Expand Down Expand Up @@ -174,6 +177,7 @@ module aes_control

// Multi-rail signals. These are outputs of the single-rail FSMs and need combining.
logic [Sp2VWidth-1:0] mr_ctrl_we;
logic [Sp2VWidth-1:0] mr_ctrl_gcm_we;
logic [Sp2VWidth-1:0] mr_alert;
logic [Sp2VWidth-1:0] mr_data_in_we;
dip_sel_e [Sp2VWidth-1:0] mr_data_in_prev_sel;
Expand Down Expand Up @@ -263,6 +267,9 @@ module aes_control
.prng_reseed_rate_i ( prng_reseed_rate_i ),
.manual_operation_i ( manual_operation_i ),
.key_touch_forces_reseed_i ( key_touch_forces_reseed_i ),
.ctrl_gcm_qe_i ( ctrl_gcm_qe_i ),
.ctrl_gcm_we_o ( mr_ctrl_gcm_we[i] ), // AND-combine
.gcm_phase_i ( gcm_phase_i ),
.start_i ( start_trigger ),
.key_iv_data_in_clear_i ( key_iv_data_in_clear_i ),
.data_out_clear_i ( data_out_clear_i ),
Expand Down Expand Up @@ -354,6 +361,9 @@ module aes_control
.prng_reseed_rate_i ( prng_reseed_rate_i ),
.manual_operation_i ( manual_operation_i ),
.key_touch_forces_reseed_i ( key_touch_forces_reseed_i ),
.ctrl_gcm_qe_i ( ctrl_gcm_qe_i ),
.ctrl_gcm_we_o ( mr_ctrl_gcm_we[i] ), // AND-combine
.gcm_phase_i ( gcm_phase_i ),
.start_i ( start_trigger ),
.key_iv_data_in_clear_i ( key_iv_data_in_clear_i ),
.data_out_clear_i ( data_out_clear_i ),
Expand Down Expand Up @@ -453,6 +463,7 @@ module aes_control

// AND: Only if all bits are high, the corresponding action should be triggered.
assign ctrl_we_o = &mr_ctrl_we;
assign ctrl_gcm_we_o = &mr_ctrl_gcm_we;
assign data_in_we_o = &mr_data_in_we;
assign key_iv_data_in_clear_we_o = &mr_key_iv_data_in_clear_we;
assign data_out_clear_we_o = &mr_data_out_clear_we;
Expand Down
21 changes: 16 additions & 5 deletions hw/ip/aes/rtl/aes_control_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ module aes_control_fsm
input prs_rate_e prng_reseed_rate_i,
input logic manual_operation_i,
input logic key_touch_forces_reseed_i,
input logic ctrl_gcm_qe_i,
output logic ctrl_gcm_we_o,
input gcm_phase_e gcm_phase_i,
input logic start_i,
input logic key_iv_data_in_clear_i,
input logic data_out_clear_i,
Expand Down Expand Up @@ -176,6 +179,10 @@ module aes_control_fsm
logic block_ctr_expr;
logic block_ctr_decr;

// TODO: Use this signal to generate the controls for the various GCM phases.
gcm_phase_e unused_gcm_phase;
assign unused_gcm_phase = gcm_phase_i;

// Software updates IV in chunks of 32 bits, the counter updates SliceSizeCtr bits at a time.
// Convert word write enable to internal half-word write enable.
assign iv_qe = {iv_qe_i[3], iv_qe_i[3], iv_qe_i[2], iv_qe_i[2],
Expand Down Expand Up @@ -267,8 +274,9 @@ module aes_control_fsm
iv_sel_o = IV_INPUT;
iv_we_o = {NumSlicesCtr{1'b0}};

// Control register
ctrl_we_o = 1'b0;
// Control registers
ctrl_we_o = 1'b0;
ctrl_gcm_we_o = 1'b0;

// Alert
alert_o = 1'b0;
Expand Down Expand Up @@ -333,9 +341,11 @@ module aes_control_fsm
key_init_we_o = sideload_i ? {NumSharesKey * NumRegsKey{key_sideload}} : key_init_qe_i;
iv_we_o = iv_qe;

// Updates to the control register are only allowed if the core is not about to start and
// there isn't a storage error. A storage error is unrecoverable and requires a reset.
ctrl_we_o = !ctrl_err_storage_i ? ctrl_qe_i : 1'b0;
// Updates to the main and GCM control registers are only allowed if the core is not
// about to start and there isn't a storage error. A storage error is unrecoverable and
// requires a reset.
ctrl_we_o = !ctrl_err_storage_i ? ctrl_qe_i : 1'b0;
ctrl_gcm_we_o = !ctrl_err_storage_i ? ctrl_gcm_qe_i : 1'b0;

// Control register updates clear all register status trackers.
key_init_clear = ctrl_we_o;
Expand Down Expand Up @@ -850,6 +860,7 @@ module aes_control_fsm
AES_CFB,
AES_OFB,
AES_CTR,
AES_GCM,
AES_NONE
})
`ASSERT(AesOpValid, !ctrl_err_storage_i |-> op_i inside {
Expand Down
20 changes: 20 additions & 0 deletions hw/ip/aes/rtl/aes_control_fsm_n.sv
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ module aes_control_fsm_n
input prs_rate_e prng_reseed_rate_i,
input logic manual_operation_i,
input logic key_touch_forces_reseed_i,
input logic ctrl_gcm_qe_i,
output logic ctrl_gcm_we_o,
input gcm_phase_e gcm_phase_i,
input logic start_i,
input logic key_iv_data_in_clear_i,
input logic data_out_clear_i,
Expand Down Expand Up @@ -134,6 +137,8 @@ module aes_control_fsm_n
prng_reseed_rate_i,
manual_operation_i,
key_touch_forces_reseed_i,
ctrl_gcm_qe_i,
gcm_phase_i,
start_i,
key_iv_data_in_clear_i,
data_out_clear_i,
Expand Down Expand Up @@ -174,6 +179,8 @@ module aes_control_fsm_n
prng_reseed_rate_i,
manual_operation_i,
key_touch_forces_reseed_i,
ctrl_gcm_qe_i,
gcm_phase_i,
start_i,
key_iv_data_in_clear_i,
data_out_clear_i,
Expand Down Expand Up @@ -221,6 +228,9 @@ module aes_control_fsm_n
prs_rate_e prng_reseed_rate;
logic manual_operation;
logic key_touch_forces_reseed;
logic ctrl_gcm_qe;
gcm_phase_e gcm_phase;
logic [$bits(gcm_phase)-1:0] gcm_phase_raw;
logic start;
logic key_iv_data_in_clear;
logic data_out_clear;
Expand Down Expand Up @@ -257,6 +267,8 @@ module aes_control_fsm_n
prng_reseed_rate,
manual_operation,
key_touch_forces_reseed,
ctrl_gcm_qe,
gcm_phase_raw,
start,
key_iv_data_in_clear,
data_out_clear,
Expand Down Expand Up @@ -284,9 +296,11 @@ module aes_control_fsm_n
output_lost_in_buf} = in_buf;

assign cipher_op = ciph_op_e'(cipher_op_raw);
assign gcm_phase = gcm_phase_e'(gcm_phase_raw);

// Intermediate output signals
logic ctrl_we;
logic ctrl_gcm_we;
logic alert;
logic data_in_we;
logic data_out_we;
Expand Down Expand Up @@ -350,6 +364,9 @@ module aes_control_fsm_n
.prng_reseed_rate_i ( prng_reseed_rate ),
.manual_operation_i ( manual_operation ),
.key_touch_forces_reseed_i ( key_touch_forces_reseed ),
.ctrl_gcm_qe_i ( ctrl_gcm_qe ),
.ctrl_gcm_we_o ( ctrl_gcm_we ),
.gcm_phase_i ( gcm_phase ),
.start_i ( start ),
.key_iv_data_in_clear_i ( key_iv_data_in_clear ),
.data_out_clear_i ( data_out_clear ),
Expand Down Expand Up @@ -430,6 +447,7 @@ module aes_control_fsm_n

localparam int NumOutBufBits = $bits({
ctrl_we_o,
ctrl_gcm_we_o,
alert_o,
data_in_we_o,
data_out_we_no,
Expand Down Expand Up @@ -475,6 +493,7 @@ module aes_control_fsm_n
// inverters back into the regular FSM.
assign out = {
ctrl_we,
ctrl_gcm_we,
alert,
data_in_we,
~data_out_we,
Expand Down Expand Up @@ -524,6 +543,7 @@ module aes_control_fsm_n
);

assign {ctrl_we_o,
ctrl_gcm_we_o,
alert_o,
data_in_we_o,
data_out_we_no,
Expand Down
Loading

0 comments on commit 08509c5

Please sign in to comment.