Software APIs
aes_stall_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "hw/ip/aes/model/aes_modes.h"
8 #include "sw/device/lib/base/multibits.h"
11 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
14 #include "sw/device/lib/testing/aes_testutils.h"
15 #include "sw/device/lib/testing/entropy_testutils.h"
16 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
20 
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 static dif_aes_t aes;
27 enum {
28  kAesNumBlocks = 2,
29  // NumBytes in one block is 4x8 i.e. 32 bits in 1 block
30  kDifAesBlockNumBytes = 4,
31  kDisableEntropyAtStartEn = 1,
32 };
33 
34 static const uint8_t kKeyShare1[16] = {
35  0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
36  0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff,
37 };
38 
39 // Function to generate a new key based on provided index value
40 void generate_new_key(dif_aes_key_share_t *key, int index) {
41  uint8_t new_key_share0[sizeof(kAesModesKey128)];
42  // Generate new key share0 by XOR-ing base key with kKeyShare1*index
43  for (size_t i = 0; i < sizeof(kAesModesKey128); ++i) {
44  new_key_share0[i] = kAesModesKey128[i] ^ kKeyShare1[i] * (uint8_t)(index);
45  }
46  // Updating the key shares
47  memcpy(key->share0, new_key_share0, sizeof(key->share0));
48  memcpy(key->share1, kKeyShare1, sizeof(key->share1));
49 }
50 
51 status_t execute_test(void) {
52  bool aes_idle = false;
53  bool input_ready = false;
54  bool output_valid = false;
55 
56  // Initialize AES
57  TRY(dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes));
58  TRY(dif_aes_reset(&aes));
59 
60  // Generate key with index 0
61  generate_new_key(&key, 0);
62 
63  // Prepare transaction
64  dif_aes_transaction_t transaction = {
65  .operation = kDifAesOperationEncrypt,
66  .mode = kDifAesModeEcb,
67  .key_len = kDifAesKey128,
68  .key_provider = kDifAesKeySoftwareProvided,
69  .mask_reseeding = kDifAesReseedPerBlock,
70  .manual_operation = kDifAesManualOperationAuto,
71  .reseed_on_key_change = true,
72  .force_masks = true,
73  .ctrl_aux_lock = false,
74  };
75 
76  dif_aes_data_t plain_text[kAesNumBlocks];
77  dif_aes_data_t cipher_text[kAesNumBlocks];
78 
79  // Initialize plaintext data dynamically
80  // Create plaintext with random data
81  dif_rv_core_ibex_t rv_core_ibex;
82  TRY(dif_rv_core_ibex_init(
84  &rv_core_ibex));
85  for (uint32_t i = 0; i < ARRAYSIZE(plain_text); ++i) {
86  for (uint32_t j = 0; j < kDifAesBlockNumBytes; ++j) {
87  uint32_t rand;
88  TRY(rv_core_ibex_testutils_get_rnd_data(&rv_core_ibex, 2000, &rand));
89  plain_text[i].data[j] = rand;
90  }
91  }
92 
93  // Start the AES operation
94  // Wait for AES to be idle before starting encryption
95  aes_idle = false;
96  do {
97  TRY(dif_aes_get_status(&aes, kDifAesStatusIdle, &aes_idle));
98  } while (!aes_idle);
99 
100  TRY(dif_aes_start(&aes, &transaction, &key, NULL));
101 
102  // Variables for status checks
103  bool stall = false;
104  uint32_t num_of_blocks_loaded = 0;
105 
106  // Load multiple input blocks without reading output data
107  // to generate STALL status bit assertion
108  LOG_INFO("Loading %d blocks without reading output to create back pressure",
109  kAesNumBlocks);
110  for (uint32_t i = 0; i < kAesNumBlocks; ++i) {
111  // Wait for input ready
112  input_ready = false;
113  do {
114  TRY(dif_aes_get_status(&aes, kDifAesStatusInputReady, &input_ready));
115  } while (!input_ready);
116 
117  // Load data
118  TRY(dif_aes_load_data(&aes, plain_text[i]));
119  num_of_blocks_loaded++;
120  busy_spin_micros(1000);
121 
122  // Check for STALL condition
123  TRY(dif_aes_get_status(&aes, kDifAesStatusStall, &stall));
124  if (i > 0) {
125  TRY_CHECK(
126  stall,
127  "ERROR: AES module not STALLED as expected after loading block %d",
128  i);
129  LOG_INFO("AES module is stalled as expected after loading block %d", i);
130  break;
131  }
132  }
133 
134  if (stall) {
135  // Read output data to clear stall
136  uint32_t num_of_blocks_read = 0;
137 
138  while (num_of_blocks_read < num_of_blocks_loaded) {
139  // Wait for output valid
140  output_valid = false;
141  do {
142  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &output_valid));
143  } while (!output_valid);
144 
145  // Read output data
146  TRY(dif_aes_read_output(&aes, &cipher_text[num_of_blocks_read]));
147  num_of_blocks_read++;
148 
149  // Check if STALL bit is cleared
150  TRY(dif_aes_get_status(&aes, kDifAesStatusStall, &stall));
151  TRY_CHECK(!stall, "ERROR: Block %u not successfully read",
152  num_of_blocks_read - 1);
153  }
154  } else {
155  TRY_CHECK(stall, "ERROR:STALL condition did not occur...");
156  }
157 
158  // Finish the AES encryption operation
159  LOG_INFO("End AES encryption operation");
160  TRY(dif_aes_end(&aes));
161 
162  // Wait for AES to be idle before starting decryption
163  aes_idle = false;
164  do {
165  TRY(dif_aes_get_status(&aes, kDifAesStatusIdle, &aes_idle));
166  } while (!aes_idle);
167  LOG_INFO("AES module is idle");
168 
169  return OK_STATUS();
170 }
171 
172 bool test_main(void) {
173  LOG_INFO("Entering AES aes_stall_test Test");
174 
175  return status_ok(execute_test());
176 }