forked from lowRISC/opentitan
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[aes,sw/dv] Test AES-GCM save&restore feature #26
Draft
nasahlpa
wants to merge
2
commits into
vogelpi:aes-gcm-review
Choose a base branch
from
nasahlpa:aes_gcm_dv_save_restore
base: aes-gcm-review
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// Copyright lowRISC contributors (OpenTitan project). | ||
// Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Test processes several AES-GCM messages. During each message, at a random | ||
// item, the GCM save and restore feature is tested. Here, before the new item | ||
// is processed, the current state is saved, the registers are cleared, and the | ||
// state is restored. Then, the test continues processing the item. | ||
|
||
// scoreboard is disabled for this test | ||
class aes_gcm_save_restore_vseq extends aes_base_vseq; | ||
`uvm_object_utils(aes_gcm_save_restore_vseq) | ||
|
||
`uvm_object_new | ||
aes_message_item msg; | ||
bit rst_set; | ||
bit do_b2b = 0; | ||
|
||
task body(); | ||
`uvm_info(`gfn, $sformatf("\n\n\t ----| STARTING AES-GCM SAVE & RESTORE SEQUENCE |----\n %s", | ||
cfg.convert2string()), UVM_MEDIUM) | ||
|
||
fork | ||
// Start sideload (even if not used). | ||
start_sideload_seq(); | ||
join_none | ||
|
||
// Generate list of messages. | ||
generate_message_queue(); | ||
|
||
// Process all messages. | ||
while (message_queue.size() > 0 ) begin | ||
bit new_aad = 1; | ||
bit new_data = 1; | ||
int item_cnt = 1; | ||
int save_restore_item; | ||
int crypto_res; | ||
int aad_len, data_len; | ||
bit operation; | ||
bit [3:0][31:0] predicted_tag; | ||
bit [3:0][31:0] saved_gcm_state, saved_iv; | ||
aes_seq_item cfg_item = new(); | ||
aes_seq_item cfg_item_restored_iv = new(); | ||
aes_seq_item data_item = new(); | ||
|
||
`uvm_info(`gfn, $sformatf("Starting New Message - messages left %d", | ||
message_queue.size() ), UVM_MEDIUM) | ||
|
||
msg = message_queue.pop_back(); | ||
aad_len = msg.aad_length; | ||
data_len = msg.message_length; | ||
generate_aes_item_queue(msg); | ||
|
||
cfg_item = aes_item_queue.pop_back(); | ||
msg.add_start_msg_item(cfg_item); | ||
|
||
// Wait until the DUT is idle. This is required to start the configuration. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
// Configure the DUT. Depending on the configuration, this might trigger a PRNG reseed | ||
// operation. | ||
csr_spinwait(.ptr(ral.status.idle) , .exp_data(1'b1)); | ||
setup_dut(cfg_item); | ||
|
||
// Wait until the DUT is idle. This is required to provide key and IV. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
// Provide key, IV and data. | ||
write_data_key_iv(cfg_item, cfg_item, 1, cfg_item.manual_op, 0, 0, rst_set); | ||
if (cfg_item.manual_op && !rst_set) trigger(); | ||
if (cfg_item.manual_op && !rst_set) trigger(); | ||
|
||
// At which item do we perform the save and restore? | ||
// Do not perform before we have processed the first item and also when | ||
// handling the tag. | ||
save_restore_item = 0;//$urandom_range(2, aes_item_queue.size() - 1); | ||
|
||
// Process all items. | ||
while (aes_item_queue.size() > 0 ) begin | ||
int valid_bytes; | ||
// Wait until the DUT is idle. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
|
||
data_item = aes_item_queue.pop_back(); | ||
`uvm_info(`gfn, $sformatf("\n\t ----AES ITEM %s", | ||
data_item.convert2string()), UVM_MEDIUM) | ||
|
||
if (item_cnt == save_restore_item) begin | ||
`uvm_info(`gfn, $sformatf("Saving AES-GCM state before processing item %d", | ||
item_cnt), UVM_MEDIUM) | ||
set_gcm_phase(GCM_SAVE, 16, 0); | ||
if (cfg_item.manual_op) trigger(); | ||
// Save the current AES-GCM context. | ||
csr_spinwait(.ptr(ral.status.output_valid), .exp_data(1'b1)); | ||
read_data(saved_gcm_state, do_b2b); | ||
// Save the current IV. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
read_iv(saved_iv, do_b2b); | ||
`downcast(cfg_item_restored_iv, cfg_item.clone()); | ||
cfg_item_restored_iv.iv = saved_iv; | ||
cfg_item_restored_iv.iv[3] = '0; // Clear upper IV bits to restore the original IV. | ||
// Clear the AES IV, data in, and data out registers. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
clear_regs(2'b11); | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
`uvm_info(`gfn, $sformatf("Restoring AES-GCM state before processing item %d", | ||
item_cnt), UVM_MEDIUM) | ||
// Reconfigure the initial IV and the key. | ||
write_data_key_iv(cfg_item_restored_iv, data_item, 1, cfg_item.manual_op, | ||
0, 0, rst_set); | ||
if (cfg_item.manual_op) trigger(); | ||
if (cfg_item.manual_op) trigger(); | ||
|
||
// Restore the saved AES-GCM context. | ||
set_gcm_phase(GCM_RESTORE, 16, 1); | ||
csr_spinwait(.ptr(ral.status.input_ready), .exp_data(1'b1)); | ||
add_data(saved_gcm_state, do_b2b); | ||
// Restore the saved IV. | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
write_iv(saved_iv, do_b2b); | ||
if (cfg_item.manual_op) trigger(); | ||
`uvm_info(`gfn, $sformatf("Proceeding with item %d", item_cnt), UVM_MEDIUM) | ||
csr_spinwait(.ptr(ral.status.idle), .exp_data(1'b1)); | ||
// Enforce setting the GCM phase for the next item. | ||
new_aad = 1; | ||
new_data = 1; | ||
end | ||
|
||
if (data_item.item_type == AES_GCM_AAD) begin | ||
if (new_aad || data_item.data_len[3:0] != 4'd0) begin | ||
// Configure AAD phase as this is either the first AAD block or a | ||
// partial block. | ||
valid_bytes = data_item.data_len == 0 ? 16 : data_item.data_len; | ||
set_gcm_phase(GCM_AAD, valid_bytes, 0); | ||
new_aad = 0; | ||
end | ||
csr_spinwait(.ptr(ral.status.input_ready), .exp_data(1'b1)); | ||
add_data(data_item.data_in, do_b2b); | ||
if (cfg_item.manual_op) trigger(); | ||
// Add AAD to message. | ||
msg.add_aad_item(data_item); | ||
end else if (data_item.item_type == AES_DATA) begin | ||
if (new_data || data_item.data_len[3:0] != 4'd0) begin | ||
// Configure TEXT phase as this is either the first plaintext block or a | ||
// partial block. | ||
valid_bytes = data_item.data_len == 0 ? 16 : data_item.data_len; | ||
set_gcm_phase(GCM_TEXT, valid_bytes, 0); | ||
new_aad = 0; | ||
end | ||
csr_spinwait(.ptr(ral.status.input_ready), .exp_data(1'b1)); | ||
add_data(data_item.data_in, do_b2b); | ||
if (cfg_item.manual_op) trigger(); | ||
csr_spinwait(.ptr(ral.status.output_valid), .exp_data(1'b1)); | ||
read_data(data_item.data_out, do_b2b); | ||
// Add input and output data block to message. | ||
msg.add_data_item(data_item); | ||
end else if (data_item.item_type == AES_GCM_TAG) begin | ||
set_gcm_phase(GCM_TAG, 16, 0); | ||
csr_spinwait(.ptr(ral.status.input_ready), .exp_data(1'b1)); | ||
add_data(data_item.data_in, do_b2b); | ||
if (cfg_item.manual_op) trigger(); | ||
csr_spinwait(.ptr(ral.status.output_valid), .exp_data(1'b1)); | ||
read_data(data_item.data_out, do_b2b); | ||
// Add tag to message. | ||
msg.add_tag_item(data_item); | ||
end | ||
item_cnt++; | ||
end | ||
|
||
// Check if we got the correct output. | ||
operation = msg.aes_operation == AES_ENC ? 1'b0 : | ||
msg.aes_operation == AES_DEC ? 1'b1 : 1'b0; | ||
msg.alloc_predicted_msg(); | ||
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], | ||
data_len, aad_len, msg.input_msg, | ||
msg.input_aad, msg.output_tag, msg.predicted_msg, | ||
predicted_tag, crypto_res); | ||
|
||
// Check the error code of the c_dpi library. | ||
if (crypto_res < 0) begin | ||
// The underlying c_dpi cyrpto lib returns an error code < 0 if something | ||
// is wrong. | ||
`uvm_fatal(`gfn, "c_dpi crypto lib error detected!\n") | ||
end | ||
|
||
// Check output data. | ||
for (int n =0 ; n < data_len; n++) begin | ||
if ((msg.output_msg[n] != msg.predicted_msg[n]) && ~msg.output_cleared[n]) begin | ||
`uvm_fatal(`gfn, $sformatf(" output_msg[%d] (0x%x) != predicted_msg[%d] (0x%x) \n", | ||
n, msg.output_msg[n], n, msg.predicted_msg[n])) | ||
end | ||
end | ||
|
||
// Check tag. | ||
if (msg.aes_operation == AES_ENC) begin | ||
`uvm_info(`gfn, $sformatf("DOING TAG CHECK"), UVM_MEDIUM) | ||
predicted_tag = aes_transpose(predicted_tag); | ||
foreach(predicted_tag[n]) begin | ||
if ((predicted_tag[n] != msg.output_tag[n]) && msg.output_tag_vld) begin | ||
`uvm_fatal(`gfn, $sformatf(" predicted_tag[%d] (0x%x) != output_tag[%d] (0x%x) \n", | ||
n, predicted_tag[n], n, msg.output_tag[n])) | ||
end | ||
end | ||
end | ||
end | ||
endtask : body | ||
endclass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright lowRISC contributors (OpenTitan project). | ||
// Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
class aes_gcm_save_restore_test extends aes_base_test; | ||
|
||
`uvm_component_utils(aes_gcm_save_restore_test) | ||
`uvm_component_new | ||
|
||
|
||
virtual function void build_phase(uvm_phase phase); | ||
super.build_phase(phase); | ||
configure_env(); | ||
endfunction | ||
|
||
function void configure_env(); | ||
super.configure_env(); | ||
// disable scoreboard for this directed test | ||
cfg.en_scb = 0; | ||
cfg.error_types = 0; // no errors | ||
cfg.num_messages_min = 1; | ||
cfg.num_messages_max = 5; | ||
// message related knobs | ||
cfg.ecb_weight = 0; | ||
cfg.cbc_weight = 0; | ||
cfg.ctr_weight = 0; | ||
cfg.ofb_weight = 0; | ||
cfg.cfb_weight = 0; | ||
cfg.gcm_weight = 100; | ||
|
||
cfg.message_len_min = 16; // one block (16bytes=128bits) | ||
cfg.message_len_max = 123; // | ||
cfg.aad_len_min = 16; // | ||
cfg.aad_len_max = 123; // | ||
cfg.manual_operation_pct = 50; | ||
cfg.use_key_mask = 0; | ||
|
||
cfg.fixed_data_en = 0; | ||
cfg.fixed_key_en = 0; | ||
|
||
cfg.fixed_operation_en = 0; | ||
cfg.fixed_operation = aes_pkg::AES_DEC; | ||
|
||
cfg.fixed_keylen_en = 0; | ||
cfg.fixed_keylen = 3'b001; | ||
|
||
cfg.fixed_iv_en = 0; | ||
cfg.fixed_aad_en = 0; | ||
|
||
cfg.random_data_key_iv_order = 0; | ||
cfg.read_prob = 100; | ||
cfg.write_prob = 100; | ||
|
||
`DV_CHECK_RANDOMIZE_FATAL(cfg) | ||
endfunction | ||
endclass : aes_gcm_save_restore_test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be removed before merging this PR.
However, in the new
aes_gcm_save_restore
test I am encountering the following issue whensetup_mode = 0
.Then, we are configuring the AES using the following functions:
opentitan/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
Lines 267 to 272 in 925de96
Inside these functions, e.g., the set_operation() function, we first check whether the value we want to write is actually different to the value stored in the mirrored shadow register:
opentitan/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
Lines 132 to 137 in 925de96
When I have the following two messages:
In the second message the operation field gets not updated and stays at
AES_DEC
instead of going toAES_ENC
. The reason is because the result of the check in the function shown above is thatral.ctrl_shadowed.operation.get_mirrored_value() == AES_ENC
for the second message.
As I have now spend a lot of time debugging this issue, could you please have a look @vogelpi?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this is independent of the save and restore - I have commented it out in the
aes_gcm_save_restore_vseq
.To visualize the issue, I have expanded the
set_operation()
function as followed:When sending
I get the following output:
As shown in the waveform, the operation stays at AES_DEC although we want to switch to the AES_ENC mode for the second message.