[aes] Provide the initial key in two shares for security hardening
This commit modifies the design such that the initial key has to be
provided in two shares via separate CSRs. The actual key used for
encryption and passed to the currently unmasked cipher core is
obtained by combining/XORing the two shares in hardware.
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 d475106..1c41834 100644
--- a/hw/ip/aes/data/aes.hjson
+++ b/hw/ip/aes/data/aes.hjson
@@ -48,23 +48,46 @@
##############################################################################
# initial key registers
{ multireg: {
- name: "KEY",
+ name: "KEY_SHARE0",
desc: '''
- Initial Key Registers.
+ Initial Key Registers Share 0.
+ The actual initial key corresponds to Initial Key Registers Share 0 XORed with Initial Key Registers Share 1.
Loaded into the internal Full Key register upon starting encryption/decryption of the next block.
- All key registers must be written at least once when the key is changed, regardless of key length (write random data for unused bits).
+ All key registers (Share 0 and Share 1) must be written at least once when the key is changed, regardless of key length (write random data for unused bits).
The order in which the registers are updated does not matter.
Can only be updated when the AES unit is idle.
If the AES unit is non-idle, writes to these registers are ignored.
'''
count: "NumRegsKey",
- cname: "KEY",
+ cname: "KEY_SHARE0",
swaccess: "wo",
hwaccess: "hrw",
hwext: "true",
hwqe: "true",
fields: [
- { bits: "31:0", name: "key", desc: "Initial Key" }
+ { bits: "31:0", name: "key_share0", desc: "Initial Key Share 0" }
+ ],
+ }
+ },
+ { multireg: {
+ name: "KEY_SHARE1",
+ desc: '''
+ Initial Key Registers Share 1.
+ The actual initial key corresponds to Initial Key Registers Share 0 XORed with Initial Key Registers Share 1.
+ Loaded into the internal Full Key register upon starting encryption/decryption of the next block.
+ All key registers (Share 0 and Share 1) must be written at least once when the key is changed, regardless of key length (write random data for unused bits).
+ The order in which the registers are updated does not matter.
+ Can only be updated when the AES unit is idle.
+ If the AES unit is non-idle, writes to these registers are ignored.
+ '''
+ count: "NumRegsKey",
+ cname: "KEY_SHARE1",
+ swaccess: "wo",
+ hwaccess: "hrw",
+ hwext: "true",
+ hwqe: "true",
+ fields: [
+ { bits: "31:0", name: "key_share1", desc: "Initial Key Share 1" }
],
}
},
diff --git a/hw/ip/aes/doc/_index.md b/hw/ip/aes/doc/_index.md
index bf20f3c..05575bf 100644
--- a/hw/ip/aes/doc/_index.md
+++ b/hw/ip/aes/doc/_index.md
@@ -320,17 +320,21 @@
## Initialization
Before initialization, software must ensure that the AES unit is idle by checking {{< regref "STATUS.IDLE" >}}.
-If the AES unit is not idle, write operations to {{< regref "CTRL" >}}, the Initial Key registers {{< regref "KEY_0" >}} - {{< regref "KEY_7" >}} and initialization vector (IV) registers {{< regref "IV_0" >}} - {{< regref "IV_3" >}} are ignored.
+If the AES unit is not idle, write operations to {{< regref "CTRL" >}}, the Initial Key registers {{< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE1_7" >}} and initialization vector (IV) registers {{< regref "IV_0" >}} - {{< regref "IV_3" >}} are ignored.
To initialize the AES unit, software must first provide the configuration to the {{< regref "CTRL_SHADOWED" >}} register.
-Then software must write the initial key to the Initial Key registers {{< regref "KEY_0" >}} - {{< regref "KEY_7" >}}.
+Then software must write the initial key to the Initial Key registers {< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE1_7" >}}.
+The key is provided in two shares:
+The first share is written to {{< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE0_7" >}} and the second share is written to {{< regref "KEY_SHARE1_0" >}} - {{< regref "KEY_SHARE1_7" >}}.
+The actual initial key used for encryption corresponds to the value obtained by XORing {{< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE0_7" >}} with {{< regref "KEY_SHARE1_0" >}} - {{< regref "KEY_SHARE1_7" >}}.
Note that all registers are little-endian.
The key length is configured using the KEY_LEN field of {{< regref "CTRL_SHADOWED" >}}.
-Independent of the selected key length, software must always write all 8 32-bit registers.
+Independent of the selected key length, software must always write all 8 32-bit registers of both shares.
Each register must be written at least once.
The order in which the key registers are written does not matter.
-Anything can be written to the unused key registers, however, random data is preferred.
-For AES-128 and AES-192, the actual initial key used for encryption is formed by using the {{< regref "KEY_0" >}} - {{< regref "KEY_3" >}} and {{< regref "KEY_0" >}} - {{< regref "KEY_5" >}}, respectively.
+Anything can be written to the unused key registers of both shares, however, random data is preferred.
+For AES-128 ,the actual initial key used for encryption is formed by XORing {{< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE0_3" >}} with {{< regref "KEY_SHARE1_0" >}} - {{< regref "KEY_SHARE1_3" >}}.
+For AES-192, the actual initial key used for encryption is formed by XORing {{< regref "KEY_SHARE0_0" >}} - {{< regref "KEY_SHARE0_5" >}} with {{< regref "KEY_SHARE1_0" >}} - {{< regref "KEY_SHARE1_5" >}}.
If running in CBC, CFB, OFB or CTR mode, software must also write the IV registers {{< regref "IV_0" >}} - {{< regref "IV_3" >}}.
These registers are little-endian, but the increment of the IV in CTR mode is big-endian (see [Recommendation for Block Cipher Modes of Operation](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf)).
@@ -384,7 +388,8 @@
// Write key - Note: All registers are little-endian.
for (int j = 0; j < 8; j++) {
- REG32(AES_KEY_0(0) + j * 4) = key[j];
+ REG32(AES_KEY_SHARE0_0(0) + j * 4) = key_share0[j];
+ REG32(AES_KEY_SHARE1_0(0) + j * 4) = key_share1[j];
}
// Write IV.
diff --git a/hw/ip/aes/dv/env/aes_message_item.sv b/hw/ip/aes/dv/env/aes_message_item.sv
index 8cc0ba3..edf97ed 100644
--- a/hw/ip/aes/dv/env/aes_message_item.sv
+++ b/hw/ip/aes/dv/env/aes_message_item.sv
@@ -41,7 +41,7 @@
// predefined values for fixed mode
bit [3:0] [31:0] fixed_data = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
- bit [7:0] [31:0] fixed_key = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
+ bit [7:0] [31:0] fixed_key [2] = '{256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF, 256'h0};
bit [2:0] fixed_keylen = 3'b001;
bit fixed_operation = 1'b0;
bit [3:0] [31:0] fixed_iv = 128'h00000000000000000000000000000000;
@@ -73,7 +73,7 @@
// aes key length //
rand bit [2:0] aes_keylen;
// 256 bit key (8x32 bit) //
- rand bit [7:0][31:0] aes_key;
+ rand bit [7:0][31:0] aes_key [2];
// 256 bit initialization vector (8x32 bit) //
rand bit [3:0][31:0] aes_iv;
// configuration error //
@@ -116,7 +116,8 @@
constraint c_key {
if (fixed_key_en) {
- aes_key == fixed_key
+ aes_key[0] == fixed_key[0],
+ aes_key[1] == fixed_key[1]
};
}
@@ -200,9 +201,13 @@
str = {str, $sformatf("\n\t ----| Key Length: \t \t %03b |----\t ",
aes_keylen) };
- str = {str, $sformatf("\n\t ----| Key: \t \t ") };
+ str = {str, $sformatf("\n\t ----| Key Share 0: \t \t ") };
for(int i=0; i <8; i++) begin
- str = {str, $sformatf("%h ",aes_key[i])};
+ str = {str, $sformatf("%h ",aes_key[0][i])};
+ end
+ str = {str, $sformatf("\n\t ----| Key Share 1: \t \t ") };
+ for(int i=0; i <8; i++) begin
+ str = {str, $sformatf("%h ",aes_key[1][i])};
end
str = {str, $sformatf("\n\t ----| Key Mask: \t \t %0b |----\t ",
keymask) };
diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv
index 243b3dd..1a18e8c 100644
--- a/hw/ip/aes/dv/env/aes_scoreboard.sv
+++ b/hw/ip/aes/dv/env/aes_scoreboard.sv
@@ -104,12 +104,22 @@
endcase // case item.a_data[4:1]
end
- (!uvm_re_match("key_*", csr_name)): begin
+ (!uvm_re_match("key_share0*", csr_name)): begin
for (int i = 0; i < 8; i++) begin
- string keyname = $sformatf("key_%0d", i);
+ string keyname = $sformatf("key_share0_%0d", i);
if (keyname == csr_name) begin
- input_item.key[i] = item.a_data;
- input_item.key_vld[i] = 1'b1;
+ input_item.key[0][i] = item.a_data;
+ input_item.key_vld[0][i] = 1'b1;
+ end
+ end
+ end
+
+ (!uvm_re_match("key_share1*", csr_name)): begin
+ for (int i = 0; i < 8; i++) begin
+ string keyname = $sformatf("key_share1_%0d", i);
+ if (keyname == csr_name) begin
+ input_item.key[1][i] = item.a_data;
+ input_item.key_vld[1][i] = 1'b1;
end
end
end
@@ -143,9 +153,9 @@
// clear key
if (item.a_data[1]) begin
if(cfg.clear_reg_w_rand) begin
- input_item.key = {8{$urandom()}};
+ input_item.key = '{default: {8{$urandom()}}};
end else begin
- input_item.key = '0;
+ input_item.key = '{default: '0};
end
end
// clear IV
@@ -431,14 +441,16 @@
aes_message_item msg;
msg_fifo.get(msg);
- `uvm_info(`gfn, $sformatf("model %b, operation: %b, mode %06b, IV %h, key_len %03b, key %h ",
- cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv, msg.aes_keylen, msg.aes_key)
+ `uvm_info(`gfn, $sformatf("model %b, operation: %b, mode %06b, IV %h, key_len %03b, key share0 %h, key share1 %h ",
+ cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv, msg.aes_keylen,
+ msg.aes_key[0], msg.aes_key[1])
, UVM_MEDIUM)
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,
- msg.aes_keylen, msg.aes_key, msg.input_msg, msg.predicted_msg);
+ msg.aes_keylen, msg.aes_key[0] ^ msg.aes_key[1],
+ msg.input_msg, msg.predicted_msg);
`uvm_info(`gfn, $sformatf("\n\t ----| printing MESSAGE %s", msg.convert2string() )
, UVM_MEDIUM)
diff --git a/hw/ip/aes/dv/env/aes_seq_item.sv b/hw/ip/aes/dv/env/aes_seq_item.sv
index f03d3bf..7c84b81 100644
--- a/hw/ip/aes/dv/env/aes_seq_item.sv
+++ b/hw/ip/aes/dv/env/aes_seq_item.sv
@@ -26,10 +26,10 @@
bit [3:0] data_len = 0;
// key len 0: 128, 1: 192, 2: 256 3: NOT VALID
bit [2:0] key_len;
- // 256 bit key (8x32 bit)
- bit [7:0][31:0] key;
+ // 256 bit key (8x32 bit) in two shares, key = share0 ^ share1
+ bit [7:0][31:0] key [2];
// which fields of the key is valid
- bit [7:0] key_vld = 8'b0;
+ bit [7:0] key_vld [2] = '{8'b0, 8'b0};
// randomized data to add to queue
bit [3:0][31:0] iv;
// indicate if the initialization vector is valid
@@ -73,10 +73,12 @@
if(key_mask) begin
case (key_len)
3'b001: begin
- key[7:4] = 32'h00000000;
+ key[0][7:4] = 32'h00000000;
+ key[1][7:4] = 32'h00000000;
end
3'b010: begin
- key[7:6] = 32'h00000000;
+ key[0][7:6] = 32'h00000000;
+ key[1][7:6] = 32'h00000000;
end
default: begin
end
@@ -114,11 +116,11 @@
// if ret_celan = 1
// return 1 if all or none of the registers have been written
function bit key_clean(bit ret_clean);
- `uvm_info(`gfn, $sformatf("\n\t ----| Key status %b", key_vld), UVM_MEDIUM)
+ `uvm_info(`gfn, $sformatf("\n\t ----| Key status %b %b", key_vld[0], key_vld[1]), UVM_MEDIUM)
if(ret_clean) begin
- return ( (&key_vld) || ~(|key_vld));
+ return ( (&key_vld[0] & &key_vld[1]) || ~(|key_vld[0] | |key_vld[1]));
end else begin
- return &key_vld;
+ return (&key_vld[0] & &key_vld[1]);
end
endfunction // key_clean
@@ -139,28 +141,29 @@
function bit message_start();
case(mode)
AES_ECB: begin
- `uvm_info(`gfn, $sformatf("return key vld(%b) %b",key_vld, &key_vld), UVM_MEDIUM)
- return (&key_vld);
+ `uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b",
+ key_vld[0], key_vld[1], &key_vld[0] & &key_vld[1]), UVM_MEDIUM)
+ return (&key_vld[0] & &key_vld[1]);
end
AES_CBC: begin
- `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
- key_vld, &key_vld, iv_vld, &iv_vld), UVM_MEDIUM)
- return (&key_vld && &iv_vld);
+ `uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
+ key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
+ return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_CFB: begin
- `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
- key_vld, &key_vld, iv_vld, &iv_vld), UVM_MEDIUM)
- return (&key_vld && &iv_vld);
+ `uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
+ key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
+ return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_OFB: begin
- `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
- key_vld, &key_vld, iv_vld, &iv_vld), UVM_MEDIUM)
- return (&key_vld && &iv_vld);
+ `uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
+ key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
+ return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_CTR: begin
- `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
- key_vld, &key_vld, iv_vld, &iv_vld), UVM_MEDIUM)
- return (&key_vld && &iv_vld);
+ `uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
+ key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
+ return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
default: begin
`uvm_fatal(`gfn, $sformatf("\n\t ----| I AM IN DEFAULT CASE I SHOULD NOT BE HERE"))
@@ -172,7 +175,7 @@
function void clean();
data_in_vld = '0;
iv_vld = '0;
- key_vld = '0;
+ key_vld = '{default: '0};
data_out_vld = '0;
endfunction // clean
@@ -224,9 +227,13 @@
str = {str, $psprintf("\n\t ----| Operation: \t %s |----\t ", operation.name() ) };
str = {str, $psprintf("\n\t ----| Key len: \t %s |----\t ",
(key_len==3'b001) ? "128b" : (key_len == 3'b010) ? "192b" : "256b") };
- str = {str, $psprintf("\n\t ----| Key: \t ") };
+ str = {str, $psprintf("\n\t ----| Key Share 0: \t ") };
for(int i=0; i <8; i++) begin
- str = {str, $psprintf("%h ",key[i])};
+ str = {str, $psprintf("%h ",key[0][i])};
+ end
+ str = {str, $psprintf("\n\t ----| Key Share 1: \t ") };
+ for(int i=0; i <8; i++) begin
+ str = {str, $psprintf("%h ",key[1][i])};
end
str = {str, $sformatf("\n\t ----| Initializaion vector: \t ") };
for(int i=0; i <4; i++) begin
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 a7a8a79..5b149e7 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
@@ -80,15 +80,25 @@
endtask
- virtual task write_key(bit [7:0][31:0] key);
- csr_wr(.csr(ral.key_0), .value(key[0]));
- csr_wr(.csr(ral.key_1), .value(key[1]));
- csr_wr(.csr(ral.key_2), .value(key[2]));
- csr_wr(.csr(ral.key_3), .value(key[3]));
- csr_wr(.csr(ral.key_4), .value(key[4]));
- csr_wr(.csr(ral.key_5), .value(key[5]));
- csr_wr(.csr(ral.key_6), .value(key[6]));
- csr_wr(.csr(ral.key_7), .value(key[7]));
+ virtual task write_key(bit [7:0][31:0] key [2]);
+ // Share 0 (the masked key share = key ^ mask)
+ csr_wr(.csr(ral.key_share0_0), .value(key[0][0]));
+ csr_wr(.csr(ral.key_share0_1), .value(key[0][1]));
+ csr_wr(.csr(ral.key_share0_2), .value(key[0][2]));
+ csr_wr(.csr(ral.key_share0_3), .value(key[0][3]));
+ csr_wr(.csr(ral.key_share0_4), .value(key[0][4]));
+ csr_wr(.csr(ral.key_share0_5), .value(key[0][5]));
+ csr_wr(.csr(ral.key_share0_6), .value(key[0][6]));
+ csr_wr(.csr(ral.key_share0_7), .value(key[0][7]));
+ // Share 1 (the mask share)
+ csr_wr(.csr(ral.key_share1_0), .value(key[1][0]));
+ csr_wr(.csr(ral.key_share1_1), .value(key[1][1]));
+ csr_wr(.csr(ral.key_share1_2), .value(key[1][2]));
+ csr_wr(.csr(ral.key_share1_3), .value(key[1][3]));
+ csr_wr(.csr(ral.key_share1_4), .value(key[1][4]));
+ csr_wr(.csr(ral.key_share1_5), .value(key[1][5]));
+ csr_wr(.csr(ral.key_share1_6), .value(key[1][6]));
+ csr_wr(.csr(ral.key_share1_7), .value(key[1][7]));
endtask // write_key
@@ -199,9 +209,12 @@
endtask // generate_data_stream
- virtual task write_interleaved_data_key_iv( bit [7:0] [31:0] key, [3:0] [31:0] iv, [3:0] [31:0] data );
+ virtual task write_interleaved_data_key_iv( bit [7:0] [31:0] key [2], [3:0] [31:0] iv, [3:0] [31:0] data );
string txt="";
- string interleave_queue[] = '{ "key_0", "key_1", "key_2", "key_3", "key_4", "key_5", "key_6", "key_7",
+ string interleave_queue[] = '{ "key_share0_0", "key_share0_1", "key_share0_2", "key_share0_3",
+ "key_share0_4", "key_share0_5", "key_share0_6", "key_share0_7",
+ "key_share1_0", "key_share1_1", "key_share1_2", "key_share1_3",
+ "key_share1_4", "key_share1_5", "key_share1_6", "key_share1_7",
"data_in_0", "data_in_1", "data_in_2", "data_in_3",
"iv_0", "iv_1", "iv_2", "iv_3" };
@@ -211,14 +224,23 @@
txt = {txt, $sformatf("----|\n \t %s", interleave_queue[i]) };
case (interleave_queue[i])
- "key_0": csr_wr(.csr(ral.key_0), .value(key[0]));
- "key_1": csr_wr(.csr(ral.key_1), .value(key[1]));
- "key_2": csr_wr(.csr(ral.key_2), .value(key[2]));
- "key_3": csr_wr(.csr(ral.key_3), .value(key[3]));
- "key_4": csr_wr(.csr(ral.key_4), .value(key[4]));
- "key_5": csr_wr(.csr(ral.key_5), .value(key[5]));
- "key_6": csr_wr(.csr(ral.key_6), .value(key[6]));
- "key_7": csr_wr(.csr(ral.key_7), .value(key[7]));
+ "key_share0_0": csr_wr(.csr(ral.key_share0_0), .value(key[0][0]));
+ "key_share0_1": csr_wr(.csr(ral.key_share0_1), .value(key[0][1]));
+ "key_share0_2": csr_wr(.csr(ral.key_share0_2), .value(key[0][2]));
+ "key_share0_3": csr_wr(.csr(ral.key_share0_3), .value(key[0][3]));
+ "key_share0_4": csr_wr(.csr(ral.key_share0_4), .value(key[0][4]));
+ "key_share0_5": csr_wr(.csr(ral.key_share0_5), .value(key[0][5]));
+ "key_share0_6": csr_wr(.csr(ral.key_share0_6), .value(key[0][6]));
+ "key_share0_7": csr_wr(.csr(ral.key_share0_7), .value(key[0][7]));
+
+ "key_share1_0": csr_wr(.csr(ral.key_share1_0), .value(key[1][0]));
+ "key_share1_1": csr_wr(.csr(ral.key_share1_1), .value(key[1][1]));
+ "key_share1_2": csr_wr(.csr(ral.key_share1_2), .value(key[1][2]));
+ "key_share1_3": csr_wr(.csr(ral.key_share1_3), .value(key[1][3]));
+ "key_share1_4": csr_wr(.csr(ral.key_share1_4), .value(key[1][4]));
+ "key_share1_5": csr_wr(.csr(ral.key_share1_5), .value(key[1][5]));
+ "key_share1_6": csr_wr(.csr(ral.key_share1_6), .value(key[1][6]));
+ "key_share1_7": csr_wr(.csr(ral.key_share1_7), .value(key[1][7]));
"iv_0": csr_wr(.csr(ral.iv_0), .value(iv[0]));
"iv_1": csr_wr(.csr(ral.iv_1), .value(iv[1]));
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 74edf45..93d156b 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
@@ -14,7 +14,7 @@
parameter bit DECRYPT = 1'b1;
bit [3:0] [31:0] plain_text = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
- logic [255:0] init_key = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
+ logic [255:0] init_key [2] = '{256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF, 256'h0};
bit [3:0] [31:0] cypher_text;
bit [3:0] [31:0] decrypted_text;
logic [3:0] [31:0] read_text;
@@ -32,7 +32,7 @@
// set operation to encrypt
set_operation(ENCRYPT);
- `uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY %02h", init_key), UVM_HIGH)
+ `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);
cfg.clk_rst_vif.wait_clks(20);
@@ -55,7 +55,7 @@
// set aes to decrypt
set_operation(DECRYPT);
cfg.clk_rst_vif.wait_clks(20);
- `uvm_info(`gfn, $sformatf("\n\t ---|WRITING INIT KEY FOR DECRYPT: %02h", init_key), UVM_HIGH)
+ `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);
cfg.clk_rst_vif.wait_clks(20);
`uvm_info(`gfn, $sformatf("\n\t ---| WRITING CYPHER TEXT"), UVM_HIGH)
diff --git a/hw/ip/aes/rtl/aes_cipher_core.sv b/hw/ip/aes/rtl/aes_cipher_core.sv
index a05d5d4..b5c3e81 100644
--- a/hw/ip/aes/rtl/aes_cipher_core.sv
+++ b/hw/ip/aes/rtl/aes_cipher_core.sv
@@ -13,7 +13,7 @@
//
// If the parameter "Masking" is set to one, first-order masking is applied to the entire
// cipher core including key expand module. For details, see Rivain et al., "Provably secure
-// higher-order masking of AES" available at https://eprint.iacr.org/2010/441.pdf
+// higher-order masking of AES" available at https://eprint.iacr.org/2010/441.pdf .
//
//
// Details on the data formats
@@ -45,22 +45,22 @@
// - A 32-bit packed SystemVerilog array 32h'{ b12, b8, b4, b0 }.
//
// - The second dimension corresponds to the columns. To access complete columns, the state matrix
-// must first be transposed first. Thus state_transposed = aes_pkg::aes_transpose(state_q)
-// and then state_transposed[1] gives
+// must be transposed first. Thus state_transposed = aes_pkg::aes_transpose(state_q) and then
+// state_transposed[1] gives
// - The second column of the state matrix [ b4 b5 b6 b7 ], or
// - A 32-bit packed SystemVerilog array 32h'{ b7, b6, b5, b4 }.
//
// - The third dimension corresponds to the bytes.
//
-// Note that the CSRs are little-endian. The input sequence above is provided to 32-bit DATA_IN0 -
-// DATA_IN3 registers as
-// MSB LSB
-// - DATA_IN0 32h'{ b3 , b2 , b1 , b0 }
-// - DATA_IN1 32h'{ b7 , b6 , b4 , b4 }
-// - DATA_IN2 32h'{ b11, b10, b9 , b8 }
-// - DATA_IN3 32h'{ b15, b14, b13, b12 } .
+// Note that the CSRs are little-endian. The input sequence above is provided to 32-bit DATA_IN_0 -
+// DATA_IN_3 registers as
+// MSB LSB
+// - DATA_IN_0 32h'{ b3 , b2 , b1 , b0 }
+// - DATA_IN_1 32h'{ b7 , b6 , b4 , b4 }
+// - DATA_IN_2 32h'{ b11, b10, b9 , b8 }
+// - DATA_IN_3 32h'{ b15, b14, b13, b12 } .
//
-// The input state can thus be obtained by transposing the content of the DATA_IN0 - DATA_IN3
+// The input state can thus be obtained by transposing the content of the DATA_IN_0 - DATA_IN_3
// registers.
//
// Similarly, the implementation uses a 3-dimensional array to represent the AES keys:
@@ -80,15 +80,15 @@
// b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 ... ... b28 b29 b30 b31
//
// is mapped to the key words and registers (little-endian) as
-// MSB LSB
-// - KEY0 32h'{ b3 , b2 , b1 , b0 }
-// - KEY1 32h'{ b7 , b6 , b4 , b4 }
-// - KEY2 32h'{ b11, b10, b9 , b8 }
-// - KEY3 32h'{ b15, b14, b13, b12 }
-// - KEY4 32h'{ . . . . }
-// - KEY5 32h'{ . . . . }
-// - KEY6 32h'{ . . . . }
-// - KEY7 32h'{ b31, b30, b29, b28 } .
+// MSB LSB
+// - KEY_SHARE0_0 32h'{ b3 , b2 , b1 , b0 }
+// - KEY_SHARE0_1 32h'{ b7 , b6 , b4 , b4 }
+// - KEY_SHARE0_2 32h'{ b11, b10, b9 , b8 }
+// - KEY_SHARE0_3 32h'{ b15, b14, b13, b12 }
+// - KEY_SHARE0_4 32h'{ . . . . }
+// - KEY_SHARE0_5 32h'{ . . . . }
+// - KEY_SHARE0_6 32h'{ . . . . }
+// - KEY_SHARE0_7 32h'{ b31, b30, b29, b28 } .
`include "prim_assert.sv"
diff --git a/hw/ip/aes/rtl/aes_control.sv b/hw/ip/aes/rtl/aes_control.sv
index 617fd57..760c9f6 100644
--- a/hw/ip/aes/rtl/aes_control.sv
+++ b/hw/ip/aes/rtl/aes_control.sv
@@ -31,7 +31,7 @@
input logic prng_reseed_i,
// I/O register read/write enables
- input logic [7:0] key_init_qe_i,
+ input logic [7:0] key_init_qe_i [2],
input logic [3:0] iv_qe_i,
input logic [3:0] data_in_qe_i,
input logic [3:0] data_out_re_i,
@@ -68,7 +68,7 @@
// Initial key registers
output aes_pkg::key_init_sel_e key_init_sel_o,
- output logic [7:0] key_init_we_o,
+ output logic [7:0] key_init_we_o [2],
// IV registers
output aes_pkg::iv_sel_e iv_sel_o,
@@ -229,7 +229,7 @@
// Initial key registers
key_init_sel_o = KEY_INIT_INPUT;
- key_init_we_o = 8'h00;
+ key_init_we_o = '{8'h00, 8'h00};
// IV registers
iv_sel_o = IV_INPUT;
@@ -486,7 +486,7 @@
if (cipher_key_clear_i) begin
key_init_sel_o = KEY_INIT_CLEAR;
- key_init_we_o = 8'hFF;
+ key_init_we_o = '{8'hFF, 8'hFF};
key_clear_we_o = 1'b1;
key_init_clear = 1'b1;
end
@@ -521,14 +521,14 @@
aes_reg_status #(
.Width ( $bits(key_init_we_o) )
) u_reg_status_key_init (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
- .we_i ( key_init_we_o ),
- .use_i ( key_init_load ),
- .clear_i ( key_init_clear ),
- .arm_i ( key_init_arm ),
- .new_o ( key_init_new ),
- .clean_o ( key_init_ready )
+ .clk_i ( clk_i ),
+ .rst_ni ( rst_ni ),
+ .we_i ( {key_init_we_o[1], key_init_we_o[0]} ),
+ .use_i ( key_init_load ),
+ .clear_i ( key_init_clear ),
+ .arm_i ( key_init_arm ),
+ .new_o ( key_init_new ),
+ .clean_o ( key_init_ready )
);
// We only use clean and unused IVs. Either software/counter has updated
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index ada00de..cc3794f 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -59,12 +59,12 @@
logic [3:0][3:0][7:0] state_done [NumShares];
logic [3:0][3:0][7:0] state_out;
- logic [7:0][31:0] key_init;
- logic [7:0] key_init_qe;
- logic [7:0][31:0] key_init_d;
- logic [7:0][31:0] key_init_q;
+ logic [7:0][31:0] key_init [2];
+ logic [7:0] key_init_qe [2];
+ logic [7:0][31:0] key_init_d [2];
+ logic [7:0][31:0] key_init_q [2];
logic [7:0][31:0] key_init_cipher [NumShares];
- logic [7:0] key_init_we;
+ logic [7:0] key_init_we [2];
key_init_sel_e key_init_sel;
logic [3:0][31:0] iv;
@@ -109,6 +109,8 @@
logic cipher_data_out_clear;
logic cipher_data_out_clear_busy;
+ logic [255:0] prng_data_256;
+
// Unused signals
logic [3:0][31:0] unused_data_out_q;
@@ -118,8 +120,10 @@
always_comb begin : key_init_get
for (int i=0; i<8; i++) begin
- key_init[i] = reg2hw.key[i].q;
- key_init_qe[i] = reg2hw.key[i].qe;
+ key_init[0][i] = reg2hw.key_share0[i].q;
+ key_init_qe[0][i] = reg2hw.key_share0[i].qe;
+ key_init[1][i] = reg2hw.key_share1[i].q;
+ key_init_qe[1][i] = reg2hw.key_share1[i].qe;
end
end
@@ -148,20 +152,23 @@
//////////////////////
// Key, IV and Data //
//////////////////////
+ assign prng_data_256 = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
// Initial Key registers
always_comb begin : key_init_mux
unique case (key_init_sel)
KEY_INIT_INPUT: key_init_d = key_init;
- KEY_INIT_CLEAR: key_init_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
- default: key_init_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
+ KEY_INIT_CLEAR: key_init_d = '{default: prng_data_256};
+ default: key_init_d = '{default: prng_data_256};
endcase
end
always_ff @(posedge clk_i) begin : key_init_reg
- for (int i=0; i<8; i++) begin
- if (key_init_we[i]) begin
- key_init_q[i] <= key_init_d[i];
+ for (int s=0; s<2; s++) begin
+ for (int i=0; i<8; i++) begin
+ if (key_init_we[s][i]) begin
+ key_init_q[s][i] <= key_init_d[s][i];
+ end
end
end
end
@@ -265,17 +272,13 @@
end
if (!Masking) begin : gen_key_init_unmasked
- assign key_init_cipher[0] = key_init_q;
+ // Combine the two key shares for the unmasked cipher core. This causes SCA leakage of the key
+ // and thus should be avoided.
+ assign key_init_cipher[0] = key_init_q[0] ^ key_init_q[1];
end else begin : gen_key_init_masked
- // TODO: Use non-constant input masks + remove corresponding comment in aes.sv.
- // See https://github.com/lowRISC/opentitan/issues/1005
- logic [7:0][31:0] key_mask;
- assign key_mask = {32'h0000_1111, 32'h2222_3333, 32'h4444_5555, 32'h6666_7777,
- 32'h8888_9999, 32'hAAAA_BBBB, 32'hCCCC_DDDD, 32'hEEEE_FFFF};
-
- assign key_init_cipher[0] = key_init_q ^ key_mask; // Masked key share
- assign key_init_cipher[1] = key_mask; // Mask share
+ // Forward the masked key share and the mask share to the masked cipher core.
+ assign key_init_cipher = key_init_q;
end
// Cipher core
@@ -504,7 +507,8 @@
always_comb begin : key_reg_put
for (int i=0; i<8; i++) begin
- hw2reg.key[i].d = key_init_q[i];
+ hw2reg.key_share0[i].d = key_init_q[0][i];
+ hw2reg.key_share1[i].d = key_init_q[1][i];
end
end
diff --git a/hw/ip/aes/rtl/aes_reg_pkg.sv b/hw/ip/aes/rtl/aes_reg_pkg.sv
index 48d974f..db9a1b2 100644
--- a/hw/ip/aes/rtl/aes_reg_pkg.sv
+++ b/hw/ip/aes/rtl/aes_reg_pkg.sv
@@ -17,7 +17,12 @@
typedef struct packed {
logic [31:0] q;
logic qe;
- } aes_reg2hw_key_mreg_t;
+ } aes_reg2hw_key_share0_mreg_t;
+
+ typedef struct packed {
+ logic [31:0] q;
+ logic qe;
+ } aes_reg2hw_key_share1_mreg_t;
typedef struct packed {
logic [31:0] q;
@@ -81,7 +86,11 @@
typedef struct packed {
logic [31:0] d;
- } aes_hw2reg_key_mreg_t;
+ } aes_hw2reg_key_share0_mreg_t;
+
+ typedef struct packed {
+ logic [31:0] d;
+ } aes_hw2reg_key_share1_mreg_t;
typedef struct packed {
logic [31:0] d;
@@ -162,7 +171,8 @@
// Register to internal design logic //
///////////////////////////////////////
typedef struct packed {
- aes_reg2hw_key_mreg_t [7:0] key; // [680:417]
+ aes_reg2hw_key_share0_mreg_t [7:0] key_share0; // [944:681]
+ aes_reg2hw_key_share1_mreg_t [7:0] key_share1; // [680:417]
aes_reg2hw_iv_mreg_t [3:0] iv; // [416:285]
aes_reg2hw_data_in_mreg_t [3:0] data_in; // [284:153]
aes_reg2hw_data_out_mreg_t [3:0] data_out; // [152:21]
@@ -174,7 +184,8 @@
// Internal design logic to register //
///////////////////////////////////////
typedef struct packed {
- aes_hw2reg_key_mreg_t [7:0] key; // [674:419]
+ aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [930:675]
+ aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [674:419]
aes_hw2reg_iv_mreg_t [3:0] iv; // [418:291]
aes_hw2reg_data_in_mreg_t [3:0] data_in; // [290:159]
aes_hw2reg_data_out_mreg_t [3:0] data_out; // [158:31]
@@ -184,41 +195,57 @@
} aes_hw2reg_t;
// Register Address
- parameter logic [6:0] AES_KEY_0_OFFSET = 7'h 0;
- parameter logic [6:0] AES_KEY_1_OFFSET = 7'h 4;
- parameter logic [6:0] AES_KEY_2_OFFSET = 7'h 8;
- parameter logic [6:0] AES_KEY_3_OFFSET = 7'h c;
- parameter logic [6:0] AES_KEY_4_OFFSET = 7'h 10;
- parameter logic [6:0] AES_KEY_5_OFFSET = 7'h 14;
- parameter logic [6:0] AES_KEY_6_OFFSET = 7'h 18;
- parameter logic [6:0] AES_KEY_7_OFFSET = 7'h 1c;
- parameter logic [6:0] AES_IV_0_OFFSET = 7'h 20;
- parameter logic [6:0] AES_IV_1_OFFSET = 7'h 24;
- parameter logic [6:0] AES_IV_2_OFFSET = 7'h 28;
- parameter logic [6:0] AES_IV_3_OFFSET = 7'h 2c;
- parameter logic [6:0] AES_DATA_IN_0_OFFSET = 7'h 30;
- parameter logic [6:0] AES_DATA_IN_1_OFFSET = 7'h 34;
- parameter logic [6:0] AES_DATA_IN_2_OFFSET = 7'h 38;
- parameter logic [6:0] AES_DATA_IN_3_OFFSET = 7'h 3c;
- parameter logic [6:0] AES_DATA_OUT_0_OFFSET = 7'h 40;
- parameter logic [6:0] AES_DATA_OUT_1_OFFSET = 7'h 44;
- parameter logic [6:0] AES_DATA_OUT_2_OFFSET = 7'h 48;
- parameter logic [6:0] AES_DATA_OUT_3_OFFSET = 7'h 4c;
- parameter logic [6:0] AES_CTRL_SHADOWED_OFFSET = 7'h 50;
- parameter logic [6:0] AES_TRIGGER_OFFSET = 7'h 54;
- parameter logic [6:0] AES_STATUS_OFFSET = 7'h 58;
+ parameter logic [6:0] AES_KEY_SHARE0_0_OFFSET = 7'h 0;
+ parameter logic [6:0] AES_KEY_SHARE0_1_OFFSET = 7'h 4;
+ parameter logic [6:0] AES_KEY_SHARE0_2_OFFSET = 7'h 8;
+ parameter logic [6:0] AES_KEY_SHARE0_3_OFFSET = 7'h c;
+ parameter logic [6:0] AES_KEY_SHARE0_4_OFFSET = 7'h 10;
+ parameter logic [6:0] AES_KEY_SHARE0_5_OFFSET = 7'h 14;
+ parameter logic [6:0] AES_KEY_SHARE0_6_OFFSET = 7'h 18;
+ parameter logic [6:0] AES_KEY_SHARE0_7_OFFSET = 7'h 1c;
+ parameter logic [6:0] AES_KEY_SHARE1_0_OFFSET = 7'h 20;
+ parameter logic [6:0] AES_KEY_SHARE1_1_OFFSET = 7'h 24;
+ parameter logic [6:0] AES_KEY_SHARE1_2_OFFSET = 7'h 28;
+ parameter logic [6:0] AES_KEY_SHARE1_3_OFFSET = 7'h 2c;
+ parameter logic [6:0] AES_KEY_SHARE1_4_OFFSET = 7'h 30;
+ parameter logic [6:0] AES_KEY_SHARE1_5_OFFSET = 7'h 34;
+ parameter logic [6:0] AES_KEY_SHARE1_6_OFFSET = 7'h 38;
+ parameter logic [6:0] AES_KEY_SHARE1_7_OFFSET = 7'h 3c;
+ parameter logic [6:0] AES_IV_0_OFFSET = 7'h 40;
+ parameter logic [6:0] AES_IV_1_OFFSET = 7'h 44;
+ parameter logic [6:0] AES_IV_2_OFFSET = 7'h 48;
+ parameter logic [6:0] AES_IV_3_OFFSET = 7'h 4c;
+ parameter logic [6:0] AES_DATA_IN_0_OFFSET = 7'h 50;
+ parameter logic [6:0] AES_DATA_IN_1_OFFSET = 7'h 54;
+ parameter logic [6:0] AES_DATA_IN_2_OFFSET = 7'h 58;
+ parameter logic [6:0] AES_DATA_IN_3_OFFSET = 7'h 5c;
+ parameter logic [6:0] AES_DATA_OUT_0_OFFSET = 7'h 60;
+ parameter logic [6:0] AES_DATA_OUT_1_OFFSET = 7'h 64;
+ parameter logic [6:0] AES_DATA_OUT_2_OFFSET = 7'h 68;
+ parameter logic [6:0] AES_DATA_OUT_3_OFFSET = 7'h 6c;
+ parameter logic [6:0] AES_CTRL_SHADOWED_OFFSET = 7'h 70;
+ parameter logic [6:0] AES_TRIGGER_OFFSET = 7'h 74;
+ parameter logic [6:0] AES_STATUS_OFFSET = 7'h 78;
// Register Index
typedef enum int {
- AES_KEY_0,
- AES_KEY_1,
- AES_KEY_2,
- AES_KEY_3,
- AES_KEY_4,
- AES_KEY_5,
- AES_KEY_6,
- AES_KEY_7,
+ AES_KEY_SHARE0_0,
+ AES_KEY_SHARE0_1,
+ AES_KEY_SHARE0_2,
+ AES_KEY_SHARE0_3,
+ AES_KEY_SHARE0_4,
+ AES_KEY_SHARE0_5,
+ AES_KEY_SHARE0_6,
+ AES_KEY_SHARE0_7,
+ AES_KEY_SHARE1_0,
+ AES_KEY_SHARE1_1,
+ AES_KEY_SHARE1_2,
+ AES_KEY_SHARE1_3,
+ AES_KEY_SHARE1_4,
+ AES_KEY_SHARE1_5,
+ AES_KEY_SHARE1_6,
+ AES_KEY_SHARE1_7,
AES_IV_0,
AES_IV_1,
AES_IV_2,
@@ -237,30 +264,38 @@
} aes_id_e;
// Register width information to check illegal writes
- parameter logic [3:0] AES_PERMIT [23] = '{
- 4'b 1111, // index[ 0] AES_KEY_0
- 4'b 1111, // index[ 1] AES_KEY_1
- 4'b 1111, // index[ 2] AES_KEY_2
- 4'b 1111, // index[ 3] AES_KEY_3
- 4'b 1111, // index[ 4] AES_KEY_4
- 4'b 1111, // index[ 5] AES_KEY_5
- 4'b 1111, // index[ 6] AES_KEY_6
- 4'b 1111, // index[ 7] AES_KEY_7
- 4'b 1111, // index[ 8] AES_IV_0
- 4'b 1111, // index[ 9] AES_IV_1
- 4'b 1111, // index[10] AES_IV_2
- 4'b 1111, // index[11] AES_IV_3
- 4'b 1111, // index[12] AES_DATA_IN_0
- 4'b 1111, // index[13] AES_DATA_IN_1
- 4'b 1111, // index[14] AES_DATA_IN_2
- 4'b 1111, // index[15] AES_DATA_IN_3
- 4'b 1111, // index[16] AES_DATA_OUT_0
- 4'b 1111, // index[17] AES_DATA_OUT_1
- 4'b 1111, // index[18] AES_DATA_OUT_2
- 4'b 1111, // index[19] AES_DATA_OUT_3
- 4'b 0011, // index[20] AES_CTRL_SHADOWED
- 4'b 0001, // index[21] AES_TRIGGER
- 4'b 0001 // index[22] AES_STATUS
+ parameter logic [3:0] AES_PERMIT [31] = '{
+ 4'b 1111, // index[ 0] AES_KEY_SHARE0_0
+ 4'b 1111, // index[ 1] AES_KEY_SHARE0_1
+ 4'b 1111, // index[ 2] AES_KEY_SHARE0_2
+ 4'b 1111, // index[ 3] AES_KEY_SHARE0_3
+ 4'b 1111, // index[ 4] AES_KEY_SHARE0_4
+ 4'b 1111, // index[ 5] AES_KEY_SHARE0_5
+ 4'b 1111, // index[ 6] AES_KEY_SHARE0_6
+ 4'b 1111, // index[ 7] AES_KEY_SHARE0_7
+ 4'b 1111, // index[ 8] AES_KEY_SHARE1_0
+ 4'b 1111, // index[ 9] AES_KEY_SHARE1_1
+ 4'b 1111, // index[10] AES_KEY_SHARE1_2
+ 4'b 1111, // index[11] AES_KEY_SHARE1_3
+ 4'b 1111, // index[12] AES_KEY_SHARE1_4
+ 4'b 1111, // index[13] AES_KEY_SHARE1_5
+ 4'b 1111, // index[14] AES_KEY_SHARE1_6
+ 4'b 1111, // index[15] AES_KEY_SHARE1_7
+ 4'b 1111, // index[16] AES_IV_0
+ 4'b 1111, // index[17] AES_IV_1
+ 4'b 1111, // index[18] AES_IV_2
+ 4'b 1111, // index[19] AES_IV_3
+ 4'b 1111, // index[20] AES_DATA_IN_0
+ 4'b 1111, // index[21] AES_DATA_IN_1
+ 4'b 1111, // index[22] AES_DATA_IN_2
+ 4'b 1111, // index[23] AES_DATA_IN_3
+ 4'b 1111, // index[24] AES_DATA_OUT_0
+ 4'b 1111, // index[25] AES_DATA_OUT_1
+ 4'b 1111, // index[26] AES_DATA_OUT_2
+ 4'b 1111, // index[27] AES_DATA_OUT_3
+ 4'b 0011, // index[28] AES_CTRL_SHADOWED
+ 4'b 0001, // index[29] AES_TRIGGER
+ 4'b 0001 // index[30] AES_STATUS
};
endpackage
diff --git a/hw/ip/aes/rtl/aes_reg_top.sv b/hw/ip/aes/rtl/aes_reg_top.sv
index f840be0..96fe46c 100644
--- a/hw/ip/aes/rtl/aes_reg_top.sv
+++ b/hw/ip/aes/rtl/aes_reg_top.sv
@@ -71,22 +71,38 @@
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
- logic [31:0] key_0_wd;
- logic key_0_we;
- logic [31:0] key_1_wd;
- logic key_1_we;
- logic [31:0] key_2_wd;
- logic key_2_we;
- logic [31:0] key_3_wd;
- logic key_3_we;
- logic [31:0] key_4_wd;
- logic key_4_we;
- logic [31:0] key_5_wd;
- logic key_5_we;
- logic [31:0] key_6_wd;
- logic key_6_we;
- logic [31:0] key_7_wd;
- logic key_7_we;
+ logic [31:0] key_share0_0_wd;
+ logic key_share0_0_we;
+ logic [31:0] key_share0_1_wd;
+ logic key_share0_1_we;
+ logic [31:0] key_share0_2_wd;
+ logic key_share0_2_we;
+ logic [31:0] key_share0_3_wd;
+ logic key_share0_3_we;
+ logic [31:0] key_share0_4_wd;
+ logic key_share0_4_we;
+ logic [31:0] key_share0_5_wd;
+ logic key_share0_5_we;
+ logic [31:0] key_share0_6_wd;
+ logic key_share0_6_we;
+ logic [31:0] key_share0_7_wd;
+ logic key_share0_7_we;
+ logic [31:0] key_share1_0_wd;
+ logic key_share1_0_we;
+ logic [31:0] key_share1_1_wd;
+ logic key_share1_1_we;
+ logic [31:0] key_share1_2_wd;
+ logic key_share1_2_we;
+ logic [31:0] key_share1_3_wd;
+ logic key_share1_3_we;
+ logic [31:0] key_share1_4_wd;
+ logic key_share1_4_we;
+ logic [31:0] key_share1_5_wd;
+ logic key_share1_5_we;
+ logic [31:0] key_share1_6_wd;
+ logic key_share1_6_we;
+ logic [31:0] key_share1_7_wd;
+ logic key_share1_7_we;
logic [31:0] iv_0_wd;
logic iv_0_we;
logic [31:0] iv_1_wd;
@@ -146,131 +162,261 @@
// Register instances
- // Subregister 0 of Multireg key
- // R[key_0]: V(True)
+ // Subregister 0 of Multireg key_share0
+ // R[key_share0_0]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_0 (
+ ) u_key_share0_0 (
.re (1'b0),
- .we (key_0_we),
- .wd (key_0_wd),
- .d (hw2reg.key[0].d),
+ .we (key_share0_0_we),
+ .wd (key_share0_0_wd),
+ .d (hw2reg.key_share0[0].d),
.qre (),
- .qe (reg2hw.key[0].qe),
- .q (reg2hw.key[0].q ),
+ .qe (reg2hw.key_share0[0].qe),
+ .q (reg2hw.key_share0[0].q ),
.qs ()
);
- // Subregister 1 of Multireg key
- // R[key_1]: V(True)
+ // Subregister 1 of Multireg key_share0
+ // R[key_share0_1]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_1 (
+ ) u_key_share0_1 (
.re (1'b0),
- .we (key_1_we),
- .wd (key_1_wd),
- .d (hw2reg.key[1].d),
+ .we (key_share0_1_we),
+ .wd (key_share0_1_wd),
+ .d (hw2reg.key_share0[1].d),
.qre (),
- .qe (reg2hw.key[1].qe),
- .q (reg2hw.key[1].q ),
+ .qe (reg2hw.key_share0[1].qe),
+ .q (reg2hw.key_share0[1].q ),
.qs ()
);
- // Subregister 2 of Multireg key
- // R[key_2]: V(True)
+ // Subregister 2 of Multireg key_share0
+ // R[key_share0_2]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_2 (
+ ) u_key_share0_2 (
.re (1'b0),
- .we (key_2_we),
- .wd (key_2_wd),
- .d (hw2reg.key[2].d),
+ .we (key_share0_2_we),
+ .wd (key_share0_2_wd),
+ .d (hw2reg.key_share0[2].d),
.qre (),
- .qe (reg2hw.key[2].qe),
- .q (reg2hw.key[2].q ),
+ .qe (reg2hw.key_share0[2].qe),
+ .q (reg2hw.key_share0[2].q ),
.qs ()
);
- // Subregister 3 of Multireg key
- // R[key_3]: V(True)
+ // Subregister 3 of Multireg key_share0
+ // R[key_share0_3]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_3 (
+ ) u_key_share0_3 (
.re (1'b0),
- .we (key_3_we),
- .wd (key_3_wd),
- .d (hw2reg.key[3].d),
+ .we (key_share0_3_we),
+ .wd (key_share0_3_wd),
+ .d (hw2reg.key_share0[3].d),
.qre (),
- .qe (reg2hw.key[3].qe),
- .q (reg2hw.key[3].q ),
+ .qe (reg2hw.key_share0[3].qe),
+ .q (reg2hw.key_share0[3].q ),
.qs ()
);
- // Subregister 4 of Multireg key
- // R[key_4]: V(True)
+ // Subregister 4 of Multireg key_share0
+ // R[key_share0_4]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_4 (
+ ) u_key_share0_4 (
.re (1'b0),
- .we (key_4_we),
- .wd (key_4_wd),
- .d (hw2reg.key[4].d),
+ .we (key_share0_4_we),
+ .wd (key_share0_4_wd),
+ .d (hw2reg.key_share0[4].d),
.qre (),
- .qe (reg2hw.key[4].qe),
- .q (reg2hw.key[4].q ),
+ .qe (reg2hw.key_share0[4].qe),
+ .q (reg2hw.key_share0[4].q ),
.qs ()
);
- // Subregister 5 of Multireg key
- // R[key_5]: V(True)
+ // Subregister 5 of Multireg key_share0
+ // R[key_share0_5]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_5 (
+ ) u_key_share0_5 (
.re (1'b0),
- .we (key_5_we),
- .wd (key_5_wd),
- .d (hw2reg.key[5].d),
+ .we (key_share0_5_we),
+ .wd (key_share0_5_wd),
+ .d (hw2reg.key_share0[5].d),
.qre (),
- .qe (reg2hw.key[5].qe),
- .q (reg2hw.key[5].q ),
+ .qe (reg2hw.key_share0[5].qe),
+ .q (reg2hw.key_share0[5].q ),
.qs ()
);
- // Subregister 6 of Multireg key
- // R[key_6]: V(True)
+ // Subregister 6 of Multireg key_share0
+ // R[key_share0_6]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_6 (
+ ) u_key_share0_6 (
.re (1'b0),
- .we (key_6_we),
- .wd (key_6_wd),
- .d (hw2reg.key[6].d),
+ .we (key_share0_6_we),
+ .wd (key_share0_6_wd),
+ .d (hw2reg.key_share0[6].d),
.qre (),
- .qe (reg2hw.key[6].qe),
- .q (reg2hw.key[6].q ),
+ .qe (reg2hw.key_share0[6].qe),
+ .q (reg2hw.key_share0[6].q ),
.qs ()
);
- // Subregister 7 of Multireg key
- // R[key_7]: V(True)
+ // Subregister 7 of Multireg key_share0
+ // R[key_share0_7]: V(True)
prim_subreg_ext #(
.DW (32)
- ) u_key_7 (
+ ) u_key_share0_7 (
.re (1'b0),
- .we (key_7_we),
- .wd (key_7_wd),
- .d (hw2reg.key[7].d),
+ .we (key_share0_7_we),
+ .wd (key_share0_7_wd),
+ .d (hw2reg.key_share0[7].d),
.qre (),
- .qe (reg2hw.key[7].qe),
- .q (reg2hw.key[7].q ),
+ .qe (reg2hw.key_share0[7].qe),
+ .q (reg2hw.key_share0[7].q ),
+ .qs ()
+ );
+
+
+
+ // Subregister 0 of Multireg key_share1
+ // R[key_share1_0]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_0 (
+ .re (1'b0),
+ .we (key_share1_0_we),
+ .wd (key_share1_0_wd),
+ .d (hw2reg.key_share1[0].d),
+ .qre (),
+ .qe (reg2hw.key_share1[0].qe),
+ .q (reg2hw.key_share1[0].q ),
+ .qs ()
+ );
+
+ // Subregister 1 of Multireg key_share1
+ // R[key_share1_1]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_1 (
+ .re (1'b0),
+ .we (key_share1_1_we),
+ .wd (key_share1_1_wd),
+ .d (hw2reg.key_share1[1].d),
+ .qre (),
+ .qe (reg2hw.key_share1[1].qe),
+ .q (reg2hw.key_share1[1].q ),
+ .qs ()
+ );
+
+ // Subregister 2 of Multireg key_share1
+ // R[key_share1_2]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_2 (
+ .re (1'b0),
+ .we (key_share1_2_we),
+ .wd (key_share1_2_wd),
+ .d (hw2reg.key_share1[2].d),
+ .qre (),
+ .qe (reg2hw.key_share1[2].qe),
+ .q (reg2hw.key_share1[2].q ),
+ .qs ()
+ );
+
+ // Subregister 3 of Multireg key_share1
+ // R[key_share1_3]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_3 (
+ .re (1'b0),
+ .we (key_share1_3_we),
+ .wd (key_share1_3_wd),
+ .d (hw2reg.key_share1[3].d),
+ .qre (),
+ .qe (reg2hw.key_share1[3].qe),
+ .q (reg2hw.key_share1[3].q ),
+ .qs ()
+ );
+
+ // Subregister 4 of Multireg key_share1
+ // R[key_share1_4]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_4 (
+ .re (1'b0),
+ .we (key_share1_4_we),
+ .wd (key_share1_4_wd),
+ .d (hw2reg.key_share1[4].d),
+ .qre (),
+ .qe (reg2hw.key_share1[4].qe),
+ .q (reg2hw.key_share1[4].q ),
+ .qs ()
+ );
+
+ // Subregister 5 of Multireg key_share1
+ // R[key_share1_5]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_5 (
+ .re (1'b0),
+ .we (key_share1_5_we),
+ .wd (key_share1_5_wd),
+ .d (hw2reg.key_share1[5].d),
+ .qre (),
+ .qe (reg2hw.key_share1[5].qe),
+ .q (reg2hw.key_share1[5].q ),
+ .qs ()
+ );
+
+ // Subregister 6 of Multireg key_share1
+ // R[key_share1_6]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_6 (
+ .re (1'b0),
+ .we (key_share1_6_we),
+ .wd (key_share1_6_wd),
+ .d (hw2reg.key_share1[6].d),
+ .qre (),
+ .qe (reg2hw.key_share1[6].qe),
+ .q (reg2hw.key_share1[6].q ),
+ .qs ()
+ );
+
+ // Subregister 7 of Multireg key_share1
+ // R[key_share1_7]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_key_share1_7 (
+ .re (1'b0),
+ .we (key_share1_7_we),
+ .wd (key_share1_7_wd),
+ .d (hw2reg.key_share1[7].d),
+ .qre (),
+ .qe (reg2hw.key_share1[7].qe),
+ .q (reg2hw.key_share1[7].q ),
.qs ()
);
@@ -831,32 +977,40 @@
- logic [22:0] addr_hit;
+ logic [30:0] addr_hit;
always_comb begin
addr_hit = '0;
- addr_hit[ 0] = (reg_addr == AES_KEY_0_OFFSET);
- addr_hit[ 1] = (reg_addr == AES_KEY_1_OFFSET);
- addr_hit[ 2] = (reg_addr == AES_KEY_2_OFFSET);
- addr_hit[ 3] = (reg_addr == AES_KEY_3_OFFSET);
- addr_hit[ 4] = (reg_addr == AES_KEY_4_OFFSET);
- addr_hit[ 5] = (reg_addr == AES_KEY_5_OFFSET);
- addr_hit[ 6] = (reg_addr == AES_KEY_6_OFFSET);
- addr_hit[ 7] = (reg_addr == AES_KEY_7_OFFSET);
- addr_hit[ 8] = (reg_addr == AES_IV_0_OFFSET);
- addr_hit[ 9] = (reg_addr == AES_IV_1_OFFSET);
- addr_hit[10] = (reg_addr == AES_IV_2_OFFSET);
- addr_hit[11] = (reg_addr == AES_IV_3_OFFSET);
- addr_hit[12] = (reg_addr == AES_DATA_IN_0_OFFSET);
- addr_hit[13] = (reg_addr == AES_DATA_IN_1_OFFSET);
- addr_hit[14] = (reg_addr == AES_DATA_IN_2_OFFSET);
- addr_hit[15] = (reg_addr == AES_DATA_IN_3_OFFSET);
- addr_hit[16] = (reg_addr == AES_DATA_OUT_0_OFFSET);
- addr_hit[17] = (reg_addr == AES_DATA_OUT_1_OFFSET);
- addr_hit[18] = (reg_addr == AES_DATA_OUT_2_OFFSET);
- addr_hit[19] = (reg_addr == AES_DATA_OUT_3_OFFSET);
- addr_hit[20] = (reg_addr == AES_CTRL_SHADOWED_OFFSET);
- addr_hit[21] = (reg_addr == AES_TRIGGER_OFFSET);
- addr_hit[22] = (reg_addr == AES_STATUS_OFFSET);
+ addr_hit[ 0] = (reg_addr == AES_KEY_SHARE0_0_OFFSET);
+ addr_hit[ 1] = (reg_addr == AES_KEY_SHARE0_1_OFFSET);
+ addr_hit[ 2] = (reg_addr == AES_KEY_SHARE0_2_OFFSET);
+ addr_hit[ 3] = (reg_addr == AES_KEY_SHARE0_3_OFFSET);
+ addr_hit[ 4] = (reg_addr == AES_KEY_SHARE0_4_OFFSET);
+ addr_hit[ 5] = (reg_addr == AES_KEY_SHARE0_5_OFFSET);
+ addr_hit[ 6] = (reg_addr == AES_KEY_SHARE0_6_OFFSET);
+ addr_hit[ 7] = (reg_addr == AES_KEY_SHARE0_7_OFFSET);
+ addr_hit[ 8] = (reg_addr == AES_KEY_SHARE1_0_OFFSET);
+ addr_hit[ 9] = (reg_addr == AES_KEY_SHARE1_1_OFFSET);
+ addr_hit[10] = (reg_addr == AES_KEY_SHARE1_2_OFFSET);
+ addr_hit[11] = (reg_addr == AES_KEY_SHARE1_3_OFFSET);
+ addr_hit[12] = (reg_addr == AES_KEY_SHARE1_4_OFFSET);
+ addr_hit[13] = (reg_addr == AES_KEY_SHARE1_5_OFFSET);
+ addr_hit[14] = (reg_addr == AES_KEY_SHARE1_6_OFFSET);
+ addr_hit[15] = (reg_addr == AES_KEY_SHARE1_7_OFFSET);
+ addr_hit[16] = (reg_addr == AES_IV_0_OFFSET);
+ addr_hit[17] = (reg_addr == AES_IV_1_OFFSET);
+ addr_hit[18] = (reg_addr == AES_IV_2_OFFSET);
+ addr_hit[19] = (reg_addr == AES_IV_3_OFFSET);
+ addr_hit[20] = (reg_addr == AES_DATA_IN_0_OFFSET);
+ addr_hit[21] = (reg_addr == AES_DATA_IN_1_OFFSET);
+ addr_hit[22] = (reg_addr == AES_DATA_IN_2_OFFSET);
+ addr_hit[23] = (reg_addr == AES_DATA_IN_3_OFFSET);
+ addr_hit[24] = (reg_addr == AES_DATA_OUT_0_OFFSET);
+ addr_hit[25] = (reg_addr == AES_DATA_OUT_1_OFFSET);
+ addr_hit[26] = (reg_addr == AES_DATA_OUT_2_OFFSET);
+ addr_hit[27] = (reg_addr == AES_DATA_OUT_3_OFFSET);
+ addr_hit[28] = (reg_addr == AES_CTRL_SHADOWED_OFFSET);
+ addr_hit[29] = (reg_addr == AES_TRIGGER_OFFSET);
+ addr_hit[30] = (reg_addr == AES_STATUS_OFFSET);
end
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -887,96 +1041,128 @@
if (addr_hit[20] && reg_we && (AES_PERMIT[20] != (AES_PERMIT[20] & reg_be))) wr_err = 1'b1 ;
if (addr_hit[21] && reg_we && (AES_PERMIT[21] != (AES_PERMIT[21] & reg_be))) wr_err = 1'b1 ;
if (addr_hit[22] && reg_we && (AES_PERMIT[22] != (AES_PERMIT[22] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[23] && reg_we && (AES_PERMIT[23] != (AES_PERMIT[23] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[24] && reg_we && (AES_PERMIT[24] != (AES_PERMIT[24] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[25] && reg_we && (AES_PERMIT[25] != (AES_PERMIT[25] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[26] && reg_we && (AES_PERMIT[26] != (AES_PERMIT[26] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[27] && reg_we && (AES_PERMIT[27] != (AES_PERMIT[27] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[28] && reg_we && (AES_PERMIT[28] != (AES_PERMIT[28] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[29] && reg_we && (AES_PERMIT[29] != (AES_PERMIT[29] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[30] && reg_we && (AES_PERMIT[30] != (AES_PERMIT[30] & reg_be))) wr_err = 1'b1 ;
end
- assign key_0_we = addr_hit[0] & reg_we & ~wr_err;
- assign key_0_wd = reg_wdata[31:0];
+ assign key_share0_0_we = addr_hit[0] & reg_we & ~wr_err;
+ assign key_share0_0_wd = reg_wdata[31:0];
- assign key_1_we = addr_hit[1] & reg_we & ~wr_err;
- assign key_1_wd = reg_wdata[31:0];
+ assign key_share0_1_we = addr_hit[1] & reg_we & ~wr_err;
+ assign key_share0_1_wd = reg_wdata[31:0];
- assign key_2_we = addr_hit[2] & reg_we & ~wr_err;
- assign key_2_wd = reg_wdata[31:0];
+ assign key_share0_2_we = addr_hit[2] & reg_we & ~wr_err;
+ assign key_share0_2_wd = reg_wdata[31:0];
- assign key_3_we = addr_hit[3] & reg_we & ~wr_err;
- assign key_3_wd = reg_wdata[31:0];
+ assign key_share0_3_we = addr_hit[3] & reg_we & ~wr_err;
+ assign key_share0_3_wd = reg_wdata[31:0];
- assign key_4_we = addr_hit[4] & reg_we & ~wr_err;
- assign key_4_wd = reg_wdata[31:0];
+ assign key_share0_4_we = addr_hit[4] & reg_we & ~wr_err;
+ assign key_share0_4_wd = reg_wdata[31:0];
- assign key_5_we = addr_hit[5] & reg_we & ~wr_err;
- assign key_5_wd = reg_wdata[31:0];
+ assign key_share0_5_we = addr_hit[5] & reg_we & ~wr_err;
+ assign key_share0_5_wd = reg_wdata[31:0];
- assign key_6_we = addr_hit[6] & reg_we & ~wr_err;
- assign key_6_wd = reg_wdata[31:0];
+ assign key_share0_6_we = addr_hit[6] & reg_we & ~wr_err;
+ assign key_share0_6_wd = reg_wdata[31:0];
- assign key_7_we = addr_hit[7] & reg_we & ~wr_err;
- assign key_7_wd = reg_wdata[31:0];
+ assign key_share0_7_we = addr_hit[7] & reg_we & ~wr_err;
+ assign key_share0_7_wd = reg_wdata[31:0];
- assign iv_0_we = addr_hit[8] & reg_we & ~wr_err;
+ assign key_share1_0_we = addr_hit[8] & reg_we & ~wr_err;
+ assign key_share1_0_wd = reg_wdata[31:0];
+
+ assign key_share1_1_we = addr_hit[9] & reg_we & ~wr_err;
+ assign key_share1_1_wd = reg_wdata[31:0];
+
+ assign key_share1_2_we = addr_hit[10] & reg_we & ~wr_err;
+ assign key_share1_2_wd = reg_wdata[31:0];
+
+ assign key_share1_3_we = addr_hit[11] & reg_we & ~wr_err;
+ assign key_share1_3_wd = reg_wdata[31:0];
+
+ assign key_share1_4_we = addr_hit[12] & reg_we & ~wr_err;
+ assign key_share1_4_wd = reg_wdata[31:0];
+
+ assign key_share1_5_we = addr_hit[13] & reg_we & ~wr_err;
+ assign key_share1_5_wd = reg_wdata[31:0];
+
+ assign key_share1_6_we = addr_hit[14] & reg_we & ~wr_err;
+ assign key_share1_6_wd = reg_wdata[31:0];
+
+ assign key_share1_7_we = addr_hit[15] & reg_we & ~wr_err;
+ assign key_share1_7_wd = reg_wdata[31:0];
+
+ assign iv_0_we = addr_hit[16] & reg_we & ~wr_err;
assign iv_0_wd = reg_wdata[31:0];
- assign iv_1_we = addr_hit[9] & reg_we & ~wr_err;
+ assign iv_1_we = addr_hit[17] & reg_we & ~wr_err;
assign iv_1_wd = reg_wdata[31:0];
- assign iv_2_we = addr_hit[10] & reg_we & ~wr_err;
+ assign iv_2_we = addr_hit[18] & reg_we & ~wr_err;
assign iv_2_wd = reg_wdata[31:0];
- assign iv_3_we = addr_hit[11] & reg_we & ~wr_err;
+ assign iv_3_we = addr_hit[19] & reg_we & ~wr_err;
assign iv_3_wd = reg_wdata[31:0];
- assign data_in_0_we = addr_hit[12] & reg_we & ~wr_err;
+ assign data_in_0_we = addr_hit[20] & reg_we & ~wr_err;
assign data_in_0_wd = reg_wdata[31:0];
- assign data_in_1_we = addr_hit[13] & reg_we & ~wr_err;
+ assign data_in_1_we = addr_hit[21] & reg_we & ~wr_err;
assign data_in_1_wd = reg_wdata[31:0];
- assign data_in_2_we = addr_hit[14] & reg_we & ~wr_err;
+ assign data_in_2_we = addr_hit[22] & reg_we & ~wr_err;
assign data_in_2_wd = reg_wdata[31:0];
- assign data_in_3_we = addr_hit[15] & reg_we & ~wr_err;
+ assign data_in_3_we = addr_hit[23] & reg_we & ~wr_err;
assign data_in_3_wd = reg_wdata[31:0];
- assign data_out_0_re = addr_hit[16] && reg_re;
+ assign data_out_0_re = addr_hit[24] && reg_re;
- assign data_out_1_re = addr_hit[17] && reg_re;
+ assign data_out_1_re = addr_hit[25] && reg_re;
- assign data_out_2_re = addr_hit[18] && reg_re;
+ assign data_out_2_re = addr_hit[26] && reg_re;
- assign data_out_3_re = addr_hit[19] && reg_re;
+ assign data_out_3_re = addr_hit[27] && reg_re;
- assign ctrl_shadowed_operation_we = addr_hit[20] & reg_we & ~wr_err;
+ assign ctrl_shadowed_operation_we = addr_hit[28] & reg_we & ~wr_err;
assign ctrl_shadowed_operation_wd = reg_wdata[0];
- assign ctrl_shadowed_operation_re = addr_hit[20] && reg_re;
+ assign ctrl_shadowed_operation_re = addr_hit[28] && reg_re;
- assign ctrl_shadowed_mode_we = addr_hit[20] & reg_we & ~wr_err;
+ assign ctrl_shadowed_mode_we = addr_hit[28] & reg_we & ~wr_err;
assign ctrl_shadowed_mode_wd = reg_wdata[6:1];
- assign ctrl_shadowed_mode_re = addr_hit[20] && reg_re;
+ assign ctrl_shadowed_mode_re = addr_hit[28] && reg_re;
- assign ctrl_shadowed_key_len_we = addr_hit[20] & reg_we & ~wr_err;
+ assign ctrl_shadowed_key_len_we = addr_hit[28] & reg_we & ~wr_err;
assign ctrl_shadowed_key_len_wd = reg_wdata[9:7];
- assign ctrl_shadowed_key_len_re = addr_hit[20] && reg_re;
+ assign ctrl_shadowed_key_len_re = addr_hit[28] && reg_re;
- assign ctrl_shadowed_manual_operation_we = addr_hit[20] & reg_we & ~wr_err;
+ assign ctrl_shadowed_manual_operation_we = addr_hit[28] & reg_we & ~wr_err;
assign ctrl_shadowed_manual_operation_wd = reg_wdata[10];
- assign ctrl_shadowed_manual_operation_re = addr_hit[20] && reg_re;
+ assign ctrl_shadowed_manual_operation_re = addr_hit[28] && reg_re;
- assign trigger_start_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_start_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_start_wd = reg_wdata[0];
- assign trigger_key_clear_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_key_clear_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_key_clear_wd = reg_wdata[1];
- assign trigger_iv_clear_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_iv_clear_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_iv_clear_wd = reg_wdata[2];
- assign trigger_data_in_clear_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_data_in_clear_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_data_in_clear_wd = reg_wdata[3];
- assign trigger_data_out_clear_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_data_out_clear_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_data_out_clear_wd = reg_wdata[4];
- assign trigger_prng_reseed_we = addr_hit[21] & reg_we & ~wr_err;
+ assign trigger_prng_reseed_we = addr_hit[29] & reg_we & ~wr_err;
assign trigger_prng_reseed_wd = reg_wdata[5];
@@ -1052,29 +1238,61 @@
end
addr_hit[16]: begin
- reg_rdata_next[31:0] = data_out_0_qs;
+ reg_rdata_next[31:0] = '0;
end
addr_hit[17]: begin
- reg_rdata_next[31:0] = data_out_1_qs;
+ reg_rdata_next[31:0] = '0;
end
addr_hit[18]: begin
- reg_rdata_next[31:0] = data_out_2_qs;
+ reg_rdata_next[31:0] = '0;
end
addr_hit[19]: begin
- reg_rdata_next[31:0] = data_out_3_qs;
+ reg_rdata_next[31:0] = '0;
end
addr_hit[20]: begin
+ reg_rdata_next[31:0] = '0;
+ end
+
+ addr_hit[21]: begin
+ reg_rdata_next[31:0] = '0;
+ end
+
+ addr_hit[22]: begin
+ reg_rdata_next[31:0] = '0;
+ end
+
+ addr_hit[23]: begin
+ reg_rdata_next[31:0] = '0;
+ end
+
+ addr_hit[24]: begin
+ reg_rdata_next[31:0] = data_out_0_qs;
+ end
+
+ addr_hit[25]: begin
+ reg_rdata_next[31:0] = data_out_1_qs;
+ end
+
+ addr_hit[26]: begin
+ reg_rdata_next[31:0] = data_out_2_qs;
+ end
+
+ addr_hit[27]: begin
+ reg_rdata_next[31:0] = data_out_3_qs;
+ end
+
+ addr_hit[28]: 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_manual_operation_qs;
end
- addr_hit[21]: begin
+ addr_hit[29]: begin
reg_rdata_next[0] = '0;
reg_rdata_next[1] = '0;
reg_rdata_next[2] = '0;
@@ -1083,7 +1301,7 @@
reg_rdata_next[5] = '0;
end
- addr_hit[22]: begin
+ addr_hit[30]: begin
reg_rdata_next[0] = status_idle_qs;
reg_rdata_next[1] = status_stall_qs;
reg_rdata_next[2] = status_output_valid_qs;
diff --git a/sw/device/lib/aes.c b/sw/device/lib/aes.c
index 403340c..eb58a32 100644
--- a/sw/device/lib/aes.c
+++ b/sw/device/lib/aes.c
@@ -26,7 +26,8 @@
REG32(AES_CTRL_SHADOWED(0)) = cfg_val;
};
-void aes_key_put(const void *key, aes_key_len_t key_len) {
+void aes_key_put(const void *key_share0, const void *key_share1,
+ aes_key_len_t key_len) {
// Determine how many key registers to use.
size_t num_regs_key_used;
if (key_len == kAes256) {
@@ -39,12 +40,16 @@
// Write the used key registers.
for (int i = 0; i < num_regs_key_used; ++i) {
- REG32(AES_KEY_0(0) + i * sizeof(uint32_t)) = ((uint32_t *)key)[i];
+ REG32(AES_KEY_SHARE0_0(0) + i * sizeof(uint32_t)) =
+ ((uint32_t *)key_share0)[i];
+ REG32(AES_KEY_SHARE1_0(0) + i * sizeof(uint32_t)) =
+ ((uint32_t *)key_share1)[i];
}
// Write the unused key registers (the AES unit requires all key registers to
// be written).
for (int i = num_regs_key_used; i < AES_NUM_REGS_KEY; ++i) {
- REG32(AES_KEY_0(0) + i * sizeof(uint32_t)) = 0x0;
+ REG32(AES_KEY_SHARE0_0(0) + i * sizeof(uint32_t)) = 0x0;
+ REG32(AES_KEY_SHARE1_0(0) + i * sizeof(uint32_t)) = 0x0;
}
}
diff --git a/sw/device/lib/aes.h b/sw/device/lib/aes.h
index e127592..73834c3 100644
--- a/sw/device/lib/aes.h
+++ b/sw/device/lib/aes.h
@@ -61,10 +61,12 @@
/**
* Pass initial encryption key to AES unit.
*
- * @param key pointer to key.
- * @param key_len key length, given as a enum value.
+ * @param key_share0 pointer to key share 0.
+ * @param key_share1 pointer to key share 1.
+ * @param key_len key length, given as a enum value.
*/
-void aes_key_put(const void *key, aes_key_len_t key_len);
+void aes_key_put(const void *key_share0, const void *key_share1,
+ aes_key_len_t key_len);
/**
* Wait for AES unit to be ready for new input data and then
diff --git a/sw/device/tests/aes_test.c b/sw/device/tests/aes_test.c
index 9c9cd28..47477f1 100644
--- a/sw/device/tests/aes_test.c
+++ b/sw/device/tests/aes_test.c
@@ -12,18 +12,26 @@
// the Advanced Encryption Standard (AES) FIPS Publication 197 available at
// https://www.nist.gov/publications/advanced-encryption-standard-aes
-static const uint8_t plain_text_1[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
- 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
- 0xcc, 0xdd, 0xee, 0xff};
+static const uint8_t kPlainText[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+ 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
+ 0xcc, 0xdd, 0xee, 0xff};
-static const uint8_t key_32_1[32] = {
+static const uint8_t kKey[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
-static const uint8_t cipher_text_gold_32_1[16] = {
- 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
- 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89};
+static const uint8_t kCipherTextGold[16] = {0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67,
+ 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90,
+ 0x4b, 0x49, 0x60, 0x89};
+
+// The mask share, used to mask kKey. Note that the masking should not be done
+// manually. Software is expected to get the key in two shares right from the
+// beginning.
+static const uint8_t kKeyShare1[32] = {
+ 0x0f, 0x1f, 0x2f, 0x3F, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf,
+ 0xbf, 0xcf, 0xdf, 0xef, 0xff, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
+ 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa};
const test_config_t kTestConfig = {};
@@ -36,6 +44,13 @@
LOG_INFO("Running AES test");
+ // Mask the key. Note that this should not be done manually. Software is
+ // expected to get the key in two shares right from the beginning.
+ uint8_t key_share0[32];
+ for (int i = 0; i < 32; ++i) {
+ key_share0[i] = kKey[i] ^ kKeyShare1[i];
+ }
+
// Setup AES config
aes_cfg_t aes_cfg = {
.mode = kAesEcb, .key_len = kAes256, .manual_operation = false,
@@ -44,29 +59,29 @@
// Encode
aes_cfg.operation = kAesEnc;
aes_init(aes_cfg);
- aes_key_put(key_32_1, aes_cfg.key_len);
- aes_data_put_wait(plain_text_1);
+ aes_key_put(key_share0, kKeyShare1, aes_cfg.key_len);
+ aes_data_put_wait(kPlainText);
aes_data_get_wait(buffer);
// Check against golden cipher text
- for (int i = 0; i < 16; i++) {
- CHECK(cipher_text_gold_32_1[i] == buffer[i],
- "Encoded cipher_text[%d] mismatched: exp = %x, actual = %x", i,
- cipher_text_gold_32_1[i], buffer[i]);
+ for (int i = 0; i < 16; ++i) {
+ CHECK(kCipherTextGold[i] == buffer[i],
+ "Encrypted cipher_text[%d] mismatched: exp = %x, actual = %x", i,
+ kCipherTextGold[i], buffer[i]);
}
// Decode
aes_cfg.operation = kAesDec;
aes_init(aes_cfg);
- aes_key_put(key_32_1, aes_cfg.key_len);
+ aes_key_put(key_share0, kKeyShare1, aes_cfg.key_len);
aes_data_put_wait(buffer);
aes_data_get_wait(buffer);
// Check against input plain text
- for (int i = 0; i < 16; i++) {
- CHECK(plain_text_1[i] == buffer[i],
- "Decoded plain_text[%d] mismatched: exp = %x, actual = %x", i,
- plain_text_1[i], buffer[i]);
+ for (int i = 0; i < 16; ++i) {
+ CHECK(kPlainText[i] == buffer[i],
+ "Decrypted plain_text[%d] mismatched: exp = %x, actual = %x", i,
+ kPlainText[i], buffer[i]);
}
// Clear