Skip to content

Commit

Permalink
[aes/dv/dpi] Add GCM mode to DPI model
Browse files Browse the repository at this point in the history
This commit enhances the existing AES DPI model with the GCM mode.
Currently, only the OpenSSL/BoringSSL reference implementation
is supported.

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa committed Nov 12, 2024
1 parent 827d368 commit c4d470f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 17 deletions.
72 changes: 63 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,9 @@ 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 +123,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 +146,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 +179,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(ref_out);

// OpenSSL/BoringSSL
if ((int)data_len % 16) {
Expand All @@ -198,18 +229,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_raw(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 Expand Up @@ -342,6 +378,24 @@ void aes_data_put(svBitVecVal *data_o, unsigned char *data) {
return;
}

void aes_data_put_raw(svBitVecVal *data_o, unsigned char *data) {
svBitVecVal value;

// convert from 1D to 2D, write output data to simulation
for (int i = 0; i < 4; i++) {
value = 0;
for (int j = 0; j < 4; j++) {
value |= (svBitVecVal)((data[4 * i + j]) << (8 * j));
}
data_o[i] = value;
}

// free data
free(data);

return;
}

unsigned char *aes_data_unpacked_get(const svOpenArrayHandle data_i) {
unsigned char *data;
int len;
Expand Down
22 changes: 19 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,
svBitVecVal *tag_o);

/**
* Perform sub bytes operation for forward/inverse cipher operation.
Expand Down Expand Up @@ -123,6 +130,15 @@ unsigned char *aes_data_get(const svBitVecVal *data_i);
*/
void aes_data_put(svBitVecVal *data_o, unsigned char *data);

/**
* Write packed data block to simulation and free the source buffer afterwards.
* Similar to aes_data_put but does not convert the endianness.
*
* @param data_o Output data for simulation
* @param data Data to be copied to simulation, freed after the operation
*/
void aes_data_put_raw(svBitVecVal *data_o, unsigned char *data);

/**
* Get unpacked data from simulation.
*
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

0 comments on commit c4d470f

Please sign in to comment.