Software APIs
aes_interrupt_encryption_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_csrng_shared.h"
14 #include "sw/device/lib/testing/aes_testutils.h"
15 #include "sw/device/lib/testing/csrng_testutils.h"
16 #include "sw/device/lib/testing/test_framework/check.h"
18 
20 
21 enum {
22  kTestTimeout = (1000 * 1000),
23 };
24 
25 // The mask share, used to mask kKey. Note that the masking should not be done
26 // manually. Software is expected to get the key in two shares right from the
27 // beginning.
28 
29 static const unsigned char kAesModesPlainTextBlock12[32] = {
30  0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e,
31  0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03,
32  0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
33 };
34 
35 static const unsigned char kAesModesPlainTextBlock34[32] = {
36  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1,
37  0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f,
38  0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10};
39 
40 static const uint8_t kKeyShare1[] = {
41  0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf,
42  0xbf, 0xcf, 0xdf, 0xef, 0xff, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
43  0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
44 };
45 
46 OTTF_DEFINE_TEST_CONFIG();
47 
48 status_t execute_test(void) {
49  dif_aes_mode_t aes_mode;
50  dif_aes_iv_t iv_mode, iv;
51 
52  for (int test_modes = 1; test_modes < 5; test_modes++) {
53  switch (test_modes) {
54  case 1:
55  LOG_INFO("Mode: CBC");
56  aes_mode = kDifAesModeCbc;
57  memcpy(iv_mode.iv, kAesModesIvCbc, sizeof(kAesModesIvCbc));
58  break;
59  case 2:
60  LOG_INFO("Mode: CFB-128");
61  aes_mode = kDifAesModeCfb;
62  memcpy(iv_mode.iv, kAesModesIvCfb, sizeof(kAesModesIvCfb));
63  break;
64  case 3:
65  LOG_INFO("Mode: OFB");
66  aes_mode = kDifAesModeOfb;
67  memcpy(iv_mode.iv, kAesModesIvOfb, sizeof(kAesModesIvOfb));
68  break;
69  case 4:
70  LOG_INFO("Mode: CTR");
71  aes_mode = kDifAesModeCtr;
72  memcpy(iv_mode.iv, kAesModesIvCtr, sizeof(kAesModesIvCtr));
73  break;
74  }
75  // Initialise AES.
76  dif_aes_t aes;
77  TRY(dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes));
78  TRY(dif_aes_reset(&aes));
79 
80  // Mask the key. Note that this should not be done manually. Software is
81  // expected to get the key in two shares right from the beginning.
82 
83  uint8_t key_share0[sizeof(kAesModesKey128)];
84  for (int i = 0; i < sizeof(kAesModesKey128); ++i) {
85  key_share0[i] = kAesModesKey128[i] ^ kKeyShare1[i];
86  }
87 
88  // "Convert" key share byte arrays to `dif_aes_key_share_t`.
90  memcpy(key.share0, key_share0, sizeof(key.share0));
91  memcpy(key.share1, kKeyShare1, sizeof(key.share1));
92 
93  // Write the initial key share, IV and data in CSRs (known combinations).
94 
95  dif_aes_transaction_t transaction = {
96  .operation = kDifAesOperationEncrypt,
97  .mode = aes_mode,
98  .key_len = kDifAesKey128,
99  .key_provider = kDifAesKeySoftwareProvided,
100  .mask_reseeding = kDifAesReseedPerBlock,
101  .manual_operation = kDifAesManualOperationAuto,
102  .reseed_on_key_change = false,
103  .ctrl_aux_lock = false,
104  };
105 
106  TRY(dif_aes_start(&aes, &transaction, &key, &iv_mode));
107  // "Convert" plain data byte arrays to `dif_aes_data_t` array.
108 
109  enum {
110  kAesNumBlocks = 2,
111  };
112 
113  dif_aes_data_t plain_text[kAesNumBlocks], plain_text_block34[kAesNumBlocks];
114  dif_aes_data_t cipher_text[kAesNumBlocks];
115  dif_aes_data_t cipher_text_block34[kAesNumBlocks];
116 
117  memcpy(plain_text[0].data, kAesModesPlainTextBlock12,
118  sizeof(kAesModesPlainTextBlock12));
119 
120  // Encrypt kAesNumBlocks blocks.
121  TRY(dif_aes_process_data(&aes, plain_text, cipher_text,
122  (size_t)kAesNumBlocks));
123  LOG_INFO("AES Encrypt of first two blocks done");
124 
125  dif_aes_iv_t iv_encrypt1;
126  TRY(dif_aes_read_iv(&aes, &iv_encrypt1));
127 
128  bool ready = false;
129 
130  // Disable the AES unit to no longer automatically start
131  // encryption/decryption
132 
133  transaction.manual_operation = kDifAesManualOperationManual;
134 
137 
138  LOG_INFO("De-initialized Automatic operation");
139 
140  //*************** Perform an trial encryption using a different data and
141  // key. Message size, key size and mode can be chosen arbitrarily.
142 
143  TRY(dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes));
144 
145  // Mask the key. Note that this should not be done manually. Software is
146  // expected to get the key in two shares right from the beginning.
147 
148  uint8_t key_share0_t[sizeof(kAesModesKey256)];
149  for (int i = 0; i < sizeof(kAesModesKey256); ++i) {
150  key_share0_t[i] = kAesModesKey256[i] ^ kKeyShare1[i];
151  }
152 
153  // "Convert" key share byte arrays to `dif_aes_key_share_t`.
154  dif_aes_key_share_t key_t;
155  memcpy(key_t.share0, key_share0, sizeof(key_t.share0));
156  memcpy(key_t.share1, kKeyShare1, sizeof(key_t.share1));
157 
158  dif_aes_iv_t iv2;
159  memcpy(iv2.iv, kAesModesIvCtr, sizeof(iv2.iv));
160 
161  dif_aes_transaction_t transaction_trial = {
162  .operation = kDifAesOperationEncrypt,
163  .mode = kDifAesModeCtr,
164  .key_len = kDifAesKey256,
165  .key_provider = kDifAesKeySoftwareProvided,
166  .mask_reseeding = kDifAesReseedPerBlock,
167  .manual_operation = kDifAesManualOperationAuto,
168  .reseed_on_key_change = false,
169  .ctrl_aux_lock = false,
170  };
171 
172  TRY(dif_aes_start(&aes, &transaction_trial, &key_t, &iv2));
173 
174  // "Convert" plain data byte arrays to `dif_aes_data_t` array.
175  enum {
176  kAesNumBlocks_t2 = 4,
177  };
178 
179  dif_aes_data_t plain_text2[kAesNumBlocks_t2];
180  memcpy(plain_text2[0].data, kAesModesPlainText, sizeof(kAesModesPlainText));
181  TRY(dif_aes_load_data(&aes, plain_text2[0]));
182 
183  do {
184  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &ready));
185  } while (!ready);
186 
187  //*****************Trial encryption ends ******************
188  // Not checking successful encryption here since its a trial transaction
189  // Trial encryption ends here
190  // Resume the Original Encryption below
191 
192  // Using the iv read from `iv_encrypt1` for resuming the encryption of
193  // remaining 2 blocks.
194 
195  memcpy(iv.iv, &iv_encrypt1, sizeof(iv.iv));
196  transaction.manual_operation = kDifAesManualOperationAuto;
197 
198  // "Convert" key share byte arrays to `dif_aes_key_share_t`.
199  memcpy(key.share0, key_share0, sizeof(key.share0));
200  memcpy(key.share1, kKeyShare1, sizeof(key.share1));
201 
202  TRY(dif_aes_start(&aes, &transaction, &key, &iv));
203 
204  memcpy(plain_text_block34[0].data, kAesModesPlainTextBlock34,
205  sizeof(kAesModesPlainTextBlock34));
206 
207  TRY(dif_aes_get_status(&aes, kDifAesStatusInputReady, &ready));
208  LOG_INFO("Resuming Encrypt with the remaining 2 blocks of data");
209  TRY(dif_aes_process_data(&aes, plain_text_block34, cipher_text_block34,
210  (size_t)kAesNumBlocks));
211 
212  // Decrypt operation below
213  dif_aes_transaction_t transactiond = {
214  .operation = kDifAesOperationDecrypt,
215  .mode = aes_mode,
216  .key_len = kDifAesKey128,
217  .key_provider = kDifAesKeySoftwareProvided,
218  .mask_reseeding = kDifAesReseedPerBlock,
219  .manual_operation = kDifAesManualOperationAuto,
220  .reseed_on_key_change = false,
221  .ctrl_aux_lock = false,
222  };
223 
224  do {
225  TRY(dif_aes_get_status(&aes, kDifAesStatusInputReady, &ready));
226  } while (!ready);
227 
228  TRY(dif_aes_start(&aes, &transactiond, &key, &iv_mode));
229  // Finish the decryption transaction.
230  dif_aes_data_t out_data2[4];
231  for (int i = 0; i < 2; ++i) {
232  TRY(dif_aes_load_data(&aes, cipher_text[i]));
233 
234  do {
235  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &ready));
236  } while (!ready);
237 
238  TRY(dif_aes_read_output(&aes, &out_data2[i]));
239  }
240  for (int i = 2; i < 4; ++i) {
241  TRY(dif_aes_load_data(&aes, cipher_text_block34[i - 2]));
242 
243  do {
244  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &ready));
245  } while (!ready);
246 
247  TRY(dif_aes_read_output(&aes, &out_data2[i]));
248  }
249 
250  TRY(dif_aes_end(&aes));
251  CHECK_ARRAYS_EQ((uint8_t *)out_data2, kAesModesPlainText,
252  sizeof(kAesModesPlainText));
253  LOG_INFO("Decryption Successful");
254  }
255  return OK_STATUS();
256 }
257 
258 bool test_main(void) {
259  LOG_INFO("Entering AES Interrupt Encrypt Test");
260  return status_ok(execute_test());
261 }