[aes/dv/aes_model_dpi] Add DPI call to encrypt/decrypt entire messages
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
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 d5bea92..c7984e9 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
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,10 +13,11 @@
#include "aes_model_dpi.h"
-void c_dpi_aes_crypt(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) {
+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) {
// get input data from simulator
unsigned char *key = aes_key_get(key_i);
unsigned char *ref_in = aes_data_get(data_i);
@@ -37,20 +39,13 @@
if (mode != kCryptoAesEcb) {
iv = aes_data_get(iv_i);
} else {
- iv = (unsigned char *)malloc(16 * sizeof(unsigned char));
- if (!iv) {
- printf("ERROR: malloc() for c_dpi_aes_crypt failed");
- return;
- }
- memset(iv, 0, 16);
+ iv = (unsigned char *)calloc(16, sizeof(unsigned char));
+ assert(iv);
}
// allocate memory
unsigned char *ref_out = (unsigned char *)malloc(16 * sizeof(unsigned char));
- if (!ref_out) {
- printf("ERROR: malloc() for c_dpi_aes_crypt failed");
- return;
- }
+ assert(ref_out);
if (impl_i == 0) {
// The C model does ECB only. We "emulate" other modes here.
@@ -106,6 +101,92 @@
return;
}
+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) {
+ if (impl_i == 0) {
+ // The C model is currently not supported.
+ printf(
+ "ERROR: c_dpi_aes_crypt_message() currently supports OpenSSL/BoringSSL "
+ "only\n");
+ return;
+ }
+
+ // Get key from simulator.
+ unsigned char *key = aes_key_get(key_i);
+
+ // key_len_i is one-hot encoded.
+ int key_len;
+ if (*key_len_i == 0x1) {
+ key_len = 16;
+ } else if (*key_len_i == 0x2) {
+ key_len = 24;
+ } else { // 0x4
+ key_len = 32;
+ }
+
+ crypto_mode_t mode = (crypto_mode_t)*mode_i;
+
+ // Modes other than ECB require an IV from the simulator.
+ unsigned char *iv = (unsigned char *)malloc(16 * sizeof(unsigned char));
+ assert(iv);
+ if (mode != kCryptoAesEcb) {
+ // iv_i is a 1D array of words (4x32bit), but we need 16 bytes.
+ svBitVecVal value;
+ for (int i = 0; i < 4; ++i) {
+ value = iv_i[i];
+ iv[4 * i + 0] = (unsigned char)(value >> 0);
+ iv[4 * i + 1] = (unsigned char)(value >> 8);
+ iv[4 * i + 2] = (unsigned char)(value >> 16);
+ iv[4 * i + 3] = (unsigned char)(value >> 24);
+ }
+ } else {
+ memset(iv, 0, 16);
+ }
+
+ // Get message length.
+ int data_len = svSize(data_i, 1);
+
+ // Get input data from simulator.
+ unsigned char *ref_in = aes_data_unpacked_get(data_i);
+
+ // Allocate output buffer.
+ unsigned char *ref_out =
+ (unsigned char *)malloc(data_len * sizeof(unsigned char));
+ assert(ref_out);
+
+ // OpenSSL/BoringSSL
+ if ((int)data_len % 16) {
+ printf(
+ "ERROR: Message length must be a multiple of 16 bytes (the block "
+ "size).\n");
+ return;
+ }
+
+ if (impl_i == 0) {
+ // The C model is currently not supported.
+ printf(
+ "ERROR: c_dpi_aes_crypt_message() currently supports OpenSSL/BoringSSL "
+ "only\n");
+ } else { // OpenSSL/BoringSSL
+ if (!op_i) {
+ crypto_encrypt(ref_out, iv, ref_in, data_len, key, key_len, mode);
+ } else {
+ crypto_decrypt(ref_out, iv, ref_in, data_len, key, key_len, mode);
+ }
+ }
+
+ // Write output data back to simulator, free ref_out.
+ aes_data_unpacked_put(data_o, ref_out);
+
+ // Free memory.
+ free(iv);
+ free(key);
+}
+
void c_dpi_aes_sub_bytes(const unsigned char op_i, const svBitVecVal *data_i,
svBitVecVal *data_o) {
// get input data from simulator
@@ -202,10 +283,7 @@
// alloc data buffer
data = (unsigned char *)malloc(16 * sizeof(unsigned char));
- if (!data) {
- printf("ERROR: malloc() for aes_data_get failed");
- return 0;
- }
+ assert(data);
// get data from simulator, convert from 2D to 1D
for (int i = 0; i < 4; i++) {
@@ -244,10 +322,7 @@
// alloc data buffer
len = svSize(data_i, 1);
data = (unsigned char *)malloc(len * sizeof(unsigned char));
- if (!data) {
- printf("ERROR: malloc() for aes_data_unpacked_get failed");
- return 0;
- }
+ assert(data);
// get data from simulator
for (int i = 0; i < len; i++) {
@@ -284,10 +359,7 @@
// alloc data buffer
key = (unsigned char *)malloc(32 * sizeof(unsigned char));
- if (!key) {
- printf("ERROR: malloc() for aes_key_get failed");
- return 0;
- }
+ assert(key);
// get data from simulator
for (int i = 0; i < 8; i++) {
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 874235f..513eafa 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
@@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-#ifndef _AES_MODEL_DPI_H_
-#define _AES_MODEL_DPI_H_
+#ifndef OPENTITAN_HW_IP_AES_DV_AES_MODEL_DPI_AES_MODEL_DPI_H_
+#define OPENTITAN_HW_IP_AES_DV_AES_MODEL_DPI_AES_MODEL_DPI_H_
#include "svdpi.h"
@@ -19,14 +19,35 @@
* @param mode_i Cipher mode: 3'b001 = ECB, 3'b010 = CBC, 3'b100 = CTR
* @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
+ * @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 data_o Output data, 2D state matrix (3D packed array in SV)
*/
-void c_dpi_aes_crypt(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);
+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);
+
+/**
+ * Perform encryption/decryption of an entire message using OpenSSL/BoringSSL.
+ *
+ * @param impl_i Select reference impl.: 0 = C model, 1 = OpenSSL/BoringSSL
+ * @param op_i Operation: 0 = encrypt, 1 = decrypt
+ * @param mode_i Cipher mode: 3'b001 = ECB, 3'b010 = CBC, 3'b100 = CTR
+ * @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 data_o Output data, 1D byte array (open 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);
/**
* Perform sub bytes operation for forward/inverse cipher operation.
@@ -90,7 +111,7 @@
void aes_data_put(svBitVecVal *data_o, unsigned char *data);
/**
- * Get unpacked data block from simulation.
+ * Get unpacked data from simulation.
*
* @param data_i Input data from simulation
* @return Pointer to data copied to memory, 0 in case of an error
@@ -98,7 +119,7 @@
unsigned char *aes_data_unpacked_get(const svOpenArrayHandle data_i);
/**
- * Write unpacked data block to simulation and free the source buffer
+ * Write unpacked data to simulation and free the source buffer
* afterwards.
*
* @param data_o Output data for simulation
@@ -125,4 +146,4 @@
#ifdef __cplusplus
} // extern "C"
#endif
-#endif // _AES_MODEL_DPI_H_
+#endif // OPENTITAN_HW_IP_AES_DV_AES_MODEL_DPI_AES_MODEL_DPI_H_
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 a8343c4..15ca238 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
@@ -6,40 +6,51 @@
import aes_pkg::*;
// DPI-C imports
- import "DPI-C" context function void c_dpi_aes_crypt(
- input bit impl_i,
- input bit op_i,
- input bit [2:0] mode_i,
+ import "DPI-C" context function void c_dpi_aes_crypt_block(
+ input bit impl_i, // 0 = C model, 1 = OpenSSL/BoringSSL
+ input bit op_i, // 0 = encrypt, 1 = decrypt
+ input bit [2:0] mode_i, // 3'b001 = ECB, 3'b010 = CBC, 3'b100 = CTR
input bit[3:0][3:0][7:0] iv_i,
- input bit [2:0] key_len_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
);
+ 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 [2:0] mode_i, // 3'b001 = ECB, 3'b010 = CBC, 3'b100 = CTR
+ 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[]
+ );
+
import "DPI-C" context function void c_dpi_aes_sub_bytes(
- input bit op_i,
+ input bit op_i, // 0 = encrypt, 1 = decrypt
input bit[3:0][3:0][7:0] data_i,
output bit[3:0][3:0][7:0] data_o
);
import "DPI-C" context function void c_dpi_aes_shift_rows(
- input bit op_i,
+ input bit op_i, // 0 = encrypt, 1 = decrypt
input bit[3:0][3:0][7:0] data_i,
output bit[3:0][3:0][7:0] data_o
);
import "DPI-C" context function void c_dpi_aes_mix_columns(
- input bit op_i,
+ input bit op_i, // 0 = encrypt, 1 = decrypt
input bit[3:0][3:0][7:0] data_i,
output bit[3:0][3:0][7:0] data_o
);
import "DPI-C" context function void c_dpi_aes_key_expand(
- input bit op_i,
+ input bit op_i, // 0 = encrypt, 1 = decrypt
input bit [7:0] rcon_i,
input bit [3:0] round_i,
- input bit [2:0] key_len_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,
output bit[7:0][31:0] key_o
);
@@ -47,12 +58,12 @@
// wrapper function that converts from register format (4x32bit)
// to the 4x4x8 format of the c functions and back
// this ensures that RTL and refence models have same input and output format.
- function automatic void sv_dpi_aes_crypt(
- input bit impl_i,
- input bit op_i,
- input bit [2:0] mode_i,
+ 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 [2:0] mode_i, // 3'b001 = ECB, 3'b010 = CBC, 3'b100 = CTR
input bit [3:0][31:0] iv_i,
- input bit [2:0] key_len_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);
@@ -60,7 +71,7 @@
bit [3:0][3:0][7:0] iv_in, data_in, data_out;
data_in = aes_transpose(data_i);
iv_in = aes_transpose(iv_i);
- c_dpi_aes_crypt(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, data_out);
data_o = aes_transpose(data_out);
return;
endfunction
diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv
index bc37080..6735f4e 100644
--- a/hw/ip/aes/dv/env/aes_scoreboard.sv
+++ b/hw/ip/aes/dv/env/aes_scoreboard.sv
@@ -192,7 +192,7 @@
ref_fifo.get(c_item );
`uvm_info(`gfn, $sformatf("\n\t ----| GOT item "), UVM_HIGH)
- sv_dpi_aes_crypt(1'b0, c_item.operation, 3'b001, 128'b0, c_item.key_size, c_item.key,
+ sv_dpi_aes_crypt_block(1'b0, c_item.operation, 3'b001, 128'b0, c_item.key_size, c_item.key,
c_item.data_in, c_item.data_out);
`uvm_info(`gfn, $sformatf("\n\t ----| printing C MODEL %s", c_item.convert2string() )
, UVM_HIGH)