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 0d69616
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 23 deletions.
68 changes: 60 additions & 8 deletions hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
const svBitVecVal *mode_i, const svBitVecVal *iv_i,
const svBitVecVal *key_len_i,
const svBitVecVal *key_i, const svBitVecVal *data_i,
svBitVecVal *data_o) {
const svBitVecVal *aad_i, const svBitVecVal *tag_i,
svBitVecVal *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 @@ -40,6 +41,10 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
// get input data from simulator
unsigned char *key = aes_key_get(key_i);
unsigned char *ref_in = aes_data_get(data_i);
int aad_len = 16; // Always use a fixed AAD length of one block (128-bits).
unsigned char *aad_in = aes_data_get(data_i);
int tag_len = 16; // Always use the default tag size.
unsigned char *tag_in = aes_data_get(tag_i);

// Modes other than ECB require an IV from the simulator.
unsigned char *iv;
Expand All @@ -53,6 +58,9 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
// allocate memory
unsigned char *ref_out = (unsigned char *)malloc(16 * sizeof(unsigned char));
assert(ref_out);
unsigned char *tag_out =
(unsigned char *)malloc(tag_len * sizeof(unsigned char));
assert(tag_out);

if (impl == 0) {
// The C model does ECB only. We "emulate" other modes here.
Expand Down Expand Up @@ -92,6 +100,9 @@ void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
for (int i = 0; i < 16; ++i) {
ref_out[i] = data_out[i] ^ ref_in[i];
}
} else if (mode == kCryptoAesGcm) {
printf("ERROR: Mode kCryptoAesGcm only supported in OpenSSL/BoringSSL");
return;
} else { // ECB
if (!op) {
aes_encrypt_block(ref_in, key, key_len, ref_out);
Expand All @@ -101,19 +112,24 @@ 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, aad_in,
aad_len, tag_out, tag_len);
} 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, aad_in,
aad_len, tag_in, tag_len);
}
}

// write output data back to simulator, free ref_out
aes_data_put(data_o, ref_out);
aes_data_put(tag_o, tag_out);

// free memory
free(iv);
free(key);
free(ref_in);
free(aad_in);
free(tag_in);

return;
}
Expand All @@ -123,7 +139,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 +162,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 +195,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 +245,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
20 changes: 16 additions & 4 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,18 +27,23 @@ 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)
* @param data_i Input data, 2D state matrix (3D packed array in SV)
* @param aad_i Input AAD, 2D state matrix (3D packed array in SV)
* @param tag_i Input auth. tag, 2D state matrix (3D packed array in SV)
* @param data_o Output data, 2D state matrix (3D packed array in SV)
* @param tag_o Output auth. tag, 2D state matrix (3D packed array in SV)
*/
void c_dpi_aes_crypt_block(const unsigned char impl_i, const unsigned char op_i,
const svBitVecVal *mode_i, const svBitVecVal *iv_i,
const svBitVecVal *key_len_i,
const svBitVecVal *key_i, const svBitVecVal *data_i,
svBitVecVal *data_o);
const svBitVecVal *aad_i, const svBitVecVal *tag_i,
svBitVecVal *data_o, svBitVecVal *tag_o);

/**
* Perform encryption/decryption of an entire message using OpenSSL/BoringSSL.
Expand All @@ -47,20 +52,27 @@ 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, 2D state matrix (3D 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
35 changes: 26 additions & 9 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,24 +10,32 @@ 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,
input bit[3:0][3:0][7:0] data_i,
output bit[3:0][3:0][7:0] data_o
input bit[3:0][3:0][7:0] aad_i,
input bit[3:0][3:0][7:0] tag_i,
output bit[3:0][3:0][7:0] data_o,
output bit[3:0][3:0][7:0] tag_o
);

import "DPI-C" context function void c_dpi_aes_crypt_message(
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 @@ -63,21 +71,30 @@ package aes_model_dpi_pkg;
function automatic void sv_dpi_aes_crypt_block(
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
input bit [6:0] mode_i, // 7'b000_0001 = ECB, 7'000_b0010 = CBC, 7'b000_0100 = CFB,
// 7'b000_1000 = OFB, 7'b001_0000 = CTR, 7'b010_0000 = GCM,
// 7'b100_0000 = 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 [3:0][31:0] data_i,
output bit [3:0][31:0] data_o);
input bit [3:0][31:0] aad_i,
input bit [3:0][31:0] tag_i,
output bit [3:0][31:0] data_o,
output bit [3:0][31:0] tag_o);

bit [3:0][3:0][7:0] iv_in, data_in, data_out;
bit [3:0][3:0][7:0] iv_in, data_in, aad_in, tag_in, data_out, tag_out;
data_in = aes_transpose({<<8{data_i}});
aad_in = aes_transpose({<<8{aad_i}});
tag_in = aes_transpose({<<8{tag_i}});
iv_in = aes_transpose(iv_i);
key_i = {<<8{key_i}};
c_dpi_aes_crypt_block(impl_i, op_i, mode_i, iv_in, key_len_i, key_i, data_in, data_out);
c_dpi_aes_crypt_block(impl_i, op_i, mode_i, iv_in, key_len_i, key_i, data_in, aad_in, tag_in,
data_out, tag_out);
data_o = aes_transpose(data_out);
data_o = {<<8{data_o}};
tag_o = aes_transpose(tag_out);
tag_o = {<<8{tag_o}};
return;
endfunction // sv_dpi_aes_crypt_block
endpackage
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
5 changes: 4 additions & 1 deletion hw/ip/csrng/dv/env/csrng_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,10 @@ class csrng_scoreboard extends cip_base_scoreboard #(
.iv_i('h0),
.key_i(key),
.data_i(input_block),
.data_o(output_block));
.aad_i('h0),
.tag_i('h0),
.data_o(output_block),
.tag_o());
return output_block;
endfunction

Expand Down

0 comments on commit 0d69616

Please sign in to comment.