diff --git a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c index 06266e1472213f..e577f6b8ee7f1b 100644 --- a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c +++ b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.c @@ -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; } @@ -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); } } @@ -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; @@ -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( @@ -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) { @@ -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, @@ -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; diff --git a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.h b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.h index 13a4e35b362b00..ae5cd6bce59ef6 100644 --- a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.h +++ b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi.h @@ -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) @@ -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. @@ -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. * diff --git a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv index e084ec042375da..0a09c5e931cab4 100644 --- a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv +++ b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv @@ -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, @@ -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( @@ -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, diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv index 302880de010721..f9483e7c67217f 100644 --- a/hw/ip/aes/dv/env/aes_scoreboard.sv +++ b/hw/ip/aes/dv/env/aes_scoreboard.sv @@ -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; @@ -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)