Skip to content
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] Add AES-GCM model and DPI #4

Merged
merged 2 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 47 additions & 9 deletions hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
const unsigned char impl = impl_i & impl_mask;
const unsigned char op = op_i & op_mask;
const crypto_mode_t mode = (crypto_mode_t)(*mode_i & mode_mask);
if (mode == kCryptoAesNone) {
printf("ERROR: Mode kCryptoAesNone not supported by c_dpi_aes_crypt_block");
if (mode == kCryptoAesNone || mode == kCryptoAesGcm) {
printf("ERROR: Mode not supported by c_dpi_aes_crypt_block");
return;
}

Expand Down Expand Up @@ -101,9 +101,11 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
}
} else { // OpenSSL/BoringSSL
if (!op) {
crypto_encrypt(ref_out, iv, ref_in, 16, key, key_len, mode);
crypto_encrypt(ref_out, iv, ref_in, 16, key, key_len, mode, NULL, 0, NULL,
0);
} else {
crypto_decrypt(ref_out, iv, ref_in, 16, key, key_len, mode);
crypto_decrypt(ref_out, iv, ref_in, 16, key, key_len, mode, NULL, 0, NULL,
0);
}
}

Expand All @@ -123,7 +125,9 @@ void c_dpi_aes_crypt_message(unsigned char impl_i, unsigned char op_i,
const svBitVecVal *key_len_i,
const svBitVecVal *key_i,
const svOpenArrayHandle data_i,
svOpenArrayHandle data_o) {
const svOpenArrayHandle aad_i,
const svBitVecVal *tag_i, svOpenArrayHandle data_o,
svBitVecVal *tag_o) {
// Mask out unused bits as their value is undetermined.
const unsigned char impl = impl_i & impl_mask;
const unsigned char op = op_i & op_mask;
Expand All @@ -144,6 +148,11 @@ void c_dpi_aes_crypt_message(unsigned char impl_i, unsigned char op_i,
key_len = 32;
}

int tag_len = 16; // Set tag length to 128-bits. Although other bit sizes are
// supported, the hardware anyways will always generate the
// 128-bits tag and the user can decide to only use some
// a subset of these bits.

if (impl == 0) {
// The C model is currently not supported.
printf(
Expand Down Expand Up @@ -172,16 +181,40 @@ void c_dpi_aes_crypt_message(unsigned char impl_i, unsigned char op_i,
memset(iv, 0, 16);
}

unsigned char *tag_in =
(unsigned char *)malloc(tag_len * sizeof(unsigned char));
assert(tag_in);
if (mode == kCryptoAesGcm) {
// tag_i is a 1D array of words (4x32bit), but we need 16 bytes.
svBitVecVal value;
for (int i = 0; i < 4; ++i) {
value = tag_i[i];
tag_in[4 * i + 0] = (unsigned char)(value >> 0);
tag_in[4 * i + 1] = (unsigned char)(value >> 8);
tag_in[4 * i + 2] = (unsigned char)(value >> 16);
tag_in[4 * i + 3] = (unsigned char)(value >> 24);
}
} else {
memset(tag_in, 0, tag_len);
}

// Get message length.
int data_len = svSize(data_i, 1);

// Get AAD length.
int aad_len = svSize(aad_i, 1);

// Get input data from simulator.
unsigned char *ref_in = aes_data_unpacked_get(data_i);
unsigned char *aad_in = aes_data_unpacked_get(aad_i);

// Allocate output buffer.
// Allocate output buffers.
unsigned char *ref_out =
(unsigned char *)malloc(data_len * sizeof(unsigned char));
assert(ref_out);
unsigned char *tag_out =
(unsigned char *)malloc(tag_len * sizeof(unsigned char));
assert(tag_out);

// OpenSSL/BoringSSL
if ((int)data_len % 16) {
Expand All @@ -198,18 +231,23 @@ void c_dpi_aes_crypt_message(unsigned char impl_i, unsigned char op_i,
"only\n");
} else { // OpenSSL/BoringSSL
if (!op) {
crypto_encrypt(ref_out, iv, ref_in, data_len, key, key_len, mode);
crypto_encrypt(ref_out, iv, ref_in, data_len, key, key_len, mode, aad_in,
aad_len, tag_out, tag_len);
} else {
crypto_decrypt(ref_out, iv, ref_in, data_len, key, key_len, mode);
crypto_decrypt(ref_out, iv, ref_in, data_len, key, key_len, mode, aad_in,
aad_len, tag_in, tag_len);
}
}

// Write output data back to simulator, free ref_out.
// Write output data back to simulator, free ref_out & tag_out.
aes_data_unpacked_put(data_o, ref_out);
aes_data_put(tag_o, tag_out);

// Free memory.
free(iv);
free(key);
free(aad_in);
free(tag_in);
}

void c_dpi_aes_sub_bytes(const unsigned char op_i, const svBitVecVal *data_i,
Expand Down
13 changes: 10 additions & 3 deletions hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ extern "C" {
* @param op_i Operation: 0 = encrypt, 1 = decrypt
* @param mode_i Cipher mode: 6'b00_0001 = ECB, 6'00_b0010 = CBC,
* 6'b00_0100 = CFB, 6'b00_1000 = OFB,
* 6'b01_0000 = CTR, 6'b10_0000 = NONE
* 6'b01_0000 = CTR, 6'b10_0000 = GCM,
* 6'b11_1111 = NONE
* @param iv_i Initialization vector: 2D matrix (3D packed array in SV)
* @param key_len_i Key length: 3'b001 = 128b, 3'b010 = 192b, 3'b100 = 256b
* @param key_i Full input key, 1D array of words (2D packed array in SV)
Expand All @@ -47,20 +48,26 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
* @param op_i Operation: 0 = encrypt, 1 = decrypt
* @param mode_i Cipher mode: 6'b00_0001 = ECB, 6'00_b0010 = CBC,
* 6'b00_0100 = CFB, 6'b00_1000 = OFB,
* 6'b01_0000 = CTR, 6'b10_0000 = NONE
* 6'b01_0000 = CTR, 6'b10_0000 = GCM,
* 6'b11_1111 = NONE
* @param iv_i Initialization vector: 1D array of words (2D packed array
* in SV)
* @param key_len_i Key length: 3'b001 = 128b, 3'b010 = 192b, 3'b100 = 256b
* @param key_i Full input key, 1D array of words (2D packed array in SV)
* @param data_i Input data, 1D byte array (open array in SV)
* @param aad_i Input AAD, 1D byte array (open array in SV)
* @param tag_i Input auth. tag, 1D array of words (2D packed array in SV)
* @param data_o Output data, 1D byte array (open array in SV)
* @param tag_o Output auth. tag, 1D array of words (2D packed array in SV)
*/
void c_dpi_aes_crypt_message(unsigned char impl_i, unsigned char op_i,
const svBitVecVal *mode_i, const svBitVecVal *iv_i,
const svBitVecVal *key_len_i,
const svBitVecVal *key_i,
const svOpenArrayHandle data_i,
svOpenArrayHandle data_o);
const svOpenArrayHandle aad_i,
const svBitVecVal *tag_i, svOpenArrayHandle data_o,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: line break between tag_i and data_o for readability?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, this is actually enforced by lint.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted.

svBitVecVal *tag_o);

/**
* Perform sub bytes operation for forward/inverse cipher operation.
Expand Down
14 changes: 10 additions & 4 deletions hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ package aes_model_dpi_pkg;
input bit impl_i, // 0 = C model, 1 = OpenSSL/BoringSSL
input bit op_i, // 0 = encrypt, 1 = decrypt
input bit [5:0] mode_i, // 6'b00_0001 = ECB, 6'00_b0010 = CBC, 6'b00_0100 = CFB,
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = NONE
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = GCM,
// 6'b11_1111 = NONE
input bit[3:0][3:0][7:0] iv_i,
input bit [2:0] key_len_i, // 3'b001 = 128b, 3'b010 = 192b, 3'b100 = 256b
input bit [7:0][31:0] key_i,
Expand All @@ -22,12 +23,16 @@ package aes_model_dpi_pkg;
input bit impl_i, // 0 = C model, 1 = OpenSSL/BoringSSL
input bit op_i, // 0 = encrypt, 1 = decrypt
input bit [5:0] mode_i, // 6'b00_0001 = ECB, 6'00_b0010 = CBC, 6'b00_0100 = CFB,
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = NONE
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = GCM,
// 6'b11_1111 = NONE
input bit [3:0][31:0] iv_i,
input bit [2:0] key_len_i, // 3'b001 = 128b, 3'b010 = 192b, 3'b100 = 256b
input bit [7:0][31:0] key_i,
input bit [7:0] data_i[],
output bit [7:0] data_o[]
input bit [7:0] aad_i[],
input bit [3:0][31:0] tag_i,
output bit [7:0] data_o[],
output bit [3:0][31:0] tag_o
);

import "DPI-C" context function void c_dpi_aes_sub_bytes(
Expand Down Expand Up @@ -64,7 +69,8 @@ package aes_model_dpi_pkg;
input bit impl_i, // 0 = C model, 1 = OpenSSL/BoringSSL
input bit op_i, // 0 = encrypt, 1 = decrypt
input bit [5:0] mode_i, // 6'b00_0001 = ECB, 6'00_b0010 = CBC, 6'b00_0100 = CFB,
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = NONE
// 6'b00_1000 = OFB, 6'b01_0000 = CTR, 6'b10_0000 = GCM,
// 6'b11_1111 = NONE
input bit [3:0][31:0] iv_i,
input bit [2:0] key_len_i, // 3'b001 = 128b, 3'b010 = 192b, 3'b100 = 256b
input bit [7:0][31:0] key_i,
Expand Down
5 changes: 4 additions & 1 deletion hw/ip/aes/dv/env/aes_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ class aes_scoreboard extends cip_base_scoreboard #(
string txt="";
bit [3:0][31:0] tmp_input;
bit [3:0][31:0] tmp_output;
bit [3:0][31:0] tag_out;
forever begin
bit operation;
aes_message_item msg;
Expand All @@ -586,9 +587,11 @@ class aes_scoreboard extends cip_base_scoreboard #(
//ref-model / opration / chipher mode / IV / key_len / key /data i /data o //
operation = msg.aes_operation == AES_ENC ? 1'b0 :
msg.aes_operation == AES_DEC ? 1'b1 : 1'b0;
// TODO: msg.input_msg and '0 are placeholders for the actual AAD and Tag that need to
// be replaced when GCM once gets supported.
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);
msg.input_msg, msg.input_msg, '0, msg.predicted_msg, tag_out);

`uvm_info(`gfn, $sformatf("\n\t ----| printing MESSAGE %s", msg.convert2string()),
UVM_MEDIUM)
Expand Down
4 changes: 2 additions & 2 deletions hw/ip/aes/model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ In addition, this directory also contains two example applications.
2. `aes_modes`:
- Shows how to interface the OpenSSL/BoringSSL interface functions.
- Checks the output of BoringSSL/OpenSSL versus expected results.
- Supports ECB, CBC, CTR modes.
- Supports ECB, CBC, CTR, CFB, OFB, GCM modes.

How to build and run the examples
---------------------------------
Expand Down Expand Up @@ -54,4 +54,4 @@ Details of the model
- `aes_example.c/h`: Contains the first example application including test input
and expected output for ECB mode.
- `aes_modes.c/h`: Contains the second example application including test input
and expected output for ECB, CBC, CTR modes.
and expected output for ECB, CBC, CTR, CFB, OFB, GCM modes.
4 changes: 2 additions & 2 deletions hw/ip/aes/model/aes_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) {

// check state vs BoringSSL/OpenSSL
cipher_text_len = crypto_encrypt(cipher_text, iv, plain_text, 16, key,
key_len, kCryptoAesEcb);
key_len, kCryptoAesEcb, NULL, 0, NULL, 0);
if (!check_block(state, cipher_text, 0)) {
printf("SUCCESS: state matches %s cipher text\n", crypto_lib);
} else {
Expand Down Expand Up @@ -334,7 +334,7 @@ int main(int argc, char *argv[]) {

// check state vs BoringSSL/OpenSSL
crypto_decrypt(decrypted_text, iv, cipher_text, cipher_text_len, key, key_len,
kCryptoAesEcb);
kCryptoAesEcb, NULL, 0, NULL, 0);
if (!check_block(state, decrypted_text, 0)) {
printf("SUCCESS: state matches %s decrypted text\n", crypto_lib);
} else {
Expand Down
Loading
Loading