Software APIs
crypto_fi.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 "sw/device/tests/penetrationtests/firmware/fi/crypto_fi.h"
6 
7 #include "hw/ip/aes/model/aes_modes.h"
10 #include "sw/device/lib/base/status.h"
14 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
16 #include "sw/device/lib/testing/aes_testutils.h"
17 #include "sw/device/lib/testing/hmac_testutils.h"
18 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
19 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
20 #include "sw/device/lib/ujson/ujson.h"
21 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
22 #include "sw/device/tests/penetrationtests/json/crypto_fi_commands.h"
23 
24 #include "aes_regs.h"
26 #include "kmac_regs.h"
27 
28 #define SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
29  abs_mmio_write32_shadowed(shadow_reg_addr, tmp); \
30  tmp = abs_mmio_read32(shadow_reg_addr);
31 
32 #define SHADOW_REG_ACCESS_10(shadow_reg_addr, tmp) \
33  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
34  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
35  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
36  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
37  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
38  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
39  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
40  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
41  SHADOW_REG_ACCESS(shadow_reg_addr, tmp) \
42  SHADOW_REG_ACCESS(shadow_reg_addr, tmp)
43 
44 enum {
45  /**
46  * Timeout for waiting that an AES operation has completed.
47  */
48  kAesWaitTimeout = 1000000,
49 };
50 
51 static dif_aes_t aes;
52 static dif_kmac_t kmac;
53 static dif_hmac_t hmac;
54 // Interface to Ibex.
55 static dif_rv_core_ibex_t rv_core_ibex;
56 
57 static dif_aes_key_share_t aes_key_shares;
58 static dif_aes_data_t aes_plaintext;
59 
60 static const dif_hmac_transaction_t kHmacTransactionConfig = {
62  .message_endianness = kDifHmacEndiannessLittle,
63 };
64 
65 /**
66  * KMAC test description.
67  */
68 typedef struct kmac_test {
70  dif_kmac_key_t key;
71 
72  const char *message;
73  size_t message_len;
74 
75  const char *customization_string;
76  size_t customization_string_len;
77 
78  const uint32_t digest[16];
79  size_t digest_len;
80  bool digest_len_is_fixed;
81 } kmac_test_t;
82 
83 /**
84  * A single KMAC example:
85  * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
86  */
87 static const kmac_test_t kKmacTestVector = {
88  .mode = kDifKmacModeKmacLen256,
89  .key =
91  .share0 = {0x43424140, 0x47464544, 0x4b4a4948, 0x4f4e4f4c,
92  0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c},
93  .share1 = {0},
94  .length = kDifKmacKeyLen256,
95  },
96  .message =
97  "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
98  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
99  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
100  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
101  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
102  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
103  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
104  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
105  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
106  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
107  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
108  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
109  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
110  .message_len = 200,
111  .customization_string = "My Tagged Application",
112  .customization_string_len = 21,
113  .digest = {0x1c73bed5, 0x73d74e95, 0x59bb4628, 0xe3a8e3db, 0x7ae7830f,
114  0x5944ff4b, 0xb4c2f1f2, 0xceb8ebec, 0xc601ba67, 0x57b88a2e,
115  0x9b492d8d, 0x6727bbd1, 0x90117868, 0x6a300a02, 0x1d28de97,
116  0x5d3030cc},
117  .digest_len = 16,
118  .digest_len_is_fixed = false,
119 };
120 
121 static const uint8_t kKeyShare1[] = {
122  0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf,
123  0xbf, 0xcf, 0xdf, 0xef, 0xff, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
124  0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
125 };
126 
127 static dif_aes_transaction_t transaction = {
128  .operation = kDifAesOperationEncrypt,
129  .mode = kDifAesModeEcb,
130  .key_len = kDifAesKey128,
131  .manual_operation = kDifAesManualOperationManual,
132  .key_provider = kDifAesKeySoftwareProvided,
133  .mask_reseeding = kDifAesReseedPer8kBlock,
134  .reseed_on_key_change = false,
135  .force_masks = false,
136  .ctrl_aux_lock = false,
137 };
138 
139 /**
140  * Spins until the AES hardware reports a specific status bit.
141  */
142 static inline uint32_t aes_spin_until(uint32_t bit) {
143  while (true) {
144  uint32_t reg =
145  abs_mmio_read32(TOP_EARLGREY_AES_BASE_ADDR + AES_STATUS_REG_OFFSET);
146  if (bitfield_bit32_read(reg, AES_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_BIT) ||
147  bitfield_bit32_read(reg, AES_STATUS_ALERT_FATAL_FAULT_BIT)) {
148  return 1;
149  }
150  if (bitfield_bit32_read(reg, bit)) {
151  return 0;
152  }
153  }
154 }
155 
156 status_t handle_crypto_fi_aes(ujson_t *uj) {
157  // Get the test mode.
158  crypto_fi_aes_mode_t uj_data;
159  TRY(ujson_deserialize_crypto_fi_aes_mode_t(uj, &uj_data));
160  // Clear registered alerts in alert handler.
161  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
162  // Clear the AST recoverable alerts.
163  pentest_clear_sensor_recov_alerts();
164 
165  // Write the key into the AES block. Set and unset the trigger when
166  // key_trigger is true.
167  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kAesWaitTimeout);
168  if (uj_data.key_trigger) {
169  pentest_set_trigger_high();
170  }
171  TRY(dif_aes_start(&aes, &transaction, &aes_key_shares, NULL));
172  // Busy polling because AES_TESTUTILS_WAIT_FOR_STATUS seems to take longer
173  // (~100us) as expected.
174  while (!aes_testutils_get_status(&aes, kDifAesStatusInputReady))
175  ;
176  if (uj_data.key_trigger) {
177  pentest_set_trigger_low();
178  }
179 
180  // Write the plaintext into the AES block. Set and unset the trigger when
181  // plaintext_trigger is true.
182  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kAesWaitTimeout);
183  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusInputReady, true,
184  kAesWaitTimeout);
185  if (uj_data.plaintext_trigger) {
186  pentest_set_trigger_high();
187  }
188  TRY(dif_aes_load_data(&aes, aes_plaintext));
189  if (uj_data.plaintext_trigger) {
190  pentest_set_trigger_low();
191  }
192 
193  // Start the encryption. Set and unset the trigger when encrypt_trigger is
194  // true.
195  if (uj_data.encrypt_trigger) {
196  pentest_set_trigger_high();
197  }
198  asm volatile(NOP30);
200  // Busy polling because AES_TESTUTILS_WAIT_FOR_STATUS seems to take longer
201  // (~100us) as expected.
202  while (!aes_testutils_get_status(&aes, kDifAesStatusOutputValid))
203  ;
204  asm volatile(NOP30);
205  if (uj_data.encrypt_trigger) {
206  pentest_set_trigger_low();
207  }
208 
209  // Read the ciphertext. Set and unset the trigger when ciphertext_trigger is
210  // true.
211  dif_aes_data_t ciphertext;
212  if (uj_data.ciphertext_trigger) {
213  pentest_set_trigger_high();
214  }
215  TRY(dif_aes_read_output(&aes, &ciphertext));
216  if (uj_data.ciphertext_trigger) {
217  pentest_set_trigger_low();
218  }
219 
220  // Get registered alerts from alert handler.
221  reg_alerts = pentest_get_triggered_alerts();
222  // Get fatal and recoverable AST alerts from sensor controller.
223  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
224 
225  // Read ERR_STATUS register.
226  dif_rv_core_ibex_error_status_t codes;
227  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
228 
229  // Send the ciphertext and the alerts back to the host.
230  crypto_fi_aes_ciphertext_t uj_output;
231  uj_output.err_status = codes;
232  memcpy(uj_output.ciphertext, ciphertext.data, 16);
233  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
234  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
235  sizeof(sensor_alerts.alerts));
236  RESP_OK(ujson_serialize_crypto_fi_aes_ciphertext_t, uj, &uj_output);
237  return OK_STATUS();
238 }
239 
240 status_t handle_crypto_fi_init(ujson_t *uj) {
241  penetrationtest_cpuctrl_t uj_data;
242  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
243 
244  pentest_select_trigger_type(kPentestTriggerTypeSw);
245  pentest_init(kPentestTriggerSourceAes,
246  kPentestPeripheralIoDiv4 | kPentestPeripheralAes |
247  kPentestPeripheralKmac | kPentestPeripheralEdn |
248  kPentestPeripheralCsrng | kPentestPeripheralEntropy |
249  kPentestPeripheralHmac);
250  // Configure the alert handler. Alerts triggered by IP blocks are captured
251  // and reported to the test.
252  pentest_configure_alert_handler();
253 
254  // Configure the CPU for the pentest.
255  penetrationtest_device_info_t uj_output;
256  TRY(pentest_configure_cpu(
257  uj_data.icache_disable, uj_data.dummy_instr_disable,
258  uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
259  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
260  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
261  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
262 
263  // Init the AES block.
264  TRY(dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes));
265  TRY(dif_aes_reset(&aes));
266 
267  // Mask the AES key.
268  uint8_t key_share0[sizeof(kAesModesKey256)];
269  for (int i = 0; i < sizeof(kAesModesKey256); ++i) {
270  key_share0[i] = kAesModesKey256[i] ^ kKeyShare1[i];
271  }
272  // "Convert" AES key share byte arrays to `dif_aes_key_share_t`.
273  memcpy(aes_key_shares.share0, key_share0, sizeof(aes_key_shares.share0));
274  memcpy(aes_key_shares.share1, kKeyShare1, sizeof(aes_key_shares.share1));
275  // Copy the plaintext into `dif_aes_data_t`.
276  memcpy(aes_plaintext.data, kAesModesPlainText, sizeof(aes_plaintext.data));
277 
278  // Init the KMAC block.
279  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
280 
282  .entropy_mode = kDifKmacEntropyModeSoftware,
283  .entropy_fast_process = kDifToggleDisabled,
284  .entropy_seed = {0xaa25b4bf, 0x48ce8fff, 0x5a78282a, 0x48465647,
285  0x70410fef},
286  .message_big_endian = kDifToggleDisabled,
287  .output_big_endian = kDifToggleDisabled,
288  .sideload = kDifToggleDisabled,
289  .msg_mask = kDifToggleEnabled,
290  };
291 
292  TRY(dif_kmac_configure(&kmac, config));
293 
294  // Init the HMAC block.
296  TRY(dif_hmac_init(base_addr, &hmac));
297 
298  // Configure Ibex to allow reading ERR_STATUS register.
299  TRY(dif_rv_core_ibex_init(
301  &rv_core_ibex));
302 
303  // Read device ID and return to host.
304  TRY(pentest_read_device_id(uj_output.device_id));
305  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
306 
307  return OK_STATUS();
308 }
309 
310 status_t handle_crypto_fi_kmac(ujson_t *uj) {
311  // Get the test mode.
312  crypto_fi_kmac_mode_t uj_data;
313  TRY(ujson_deserialize_crypto_fi_kmac_mode_t(uj, &uj_data));
314  // Clear registered alerts in alert handler.
315  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
316  // Clear the AST recoverable alerts.
317  pentest_clear_sensor_recov_alerts();
318 
319  // Configure and write key to the KMAC block. Set and unset the trigger when
320  // key_trigger is true.
321  dif_kmac_operation_state_t kmac_operation_state;
322  if (uj_data.key_trigger) {
323  pentest_set_trigger_high();
324  }
325 
326  TRY(dif_kmac_mode_kmac_start(&kmac, &kmac_operation_state,
327  kKmacTestVector.mode, 0, &kKmacTestVector.key,
328  NULL));
329  if (uj_data.key_trigger) {
330  pentest_set_trigger_low();
331  }
332 
333  // Absorb. Set and unset the trigger when absorb_trigger is true.
334  if (uj_data.absorb_trigger) {
335  pentest_set_trigger_high();
336  }
337  TRY(dif_kmac_absorb(&kmac, &kmac_operation_state, kKmacTestVector.message,
338  kKmacTestVector.message_len, NULL));
339  if (uj_data.absorb_trigger) {
340  pentest_set_trigger_low();
341  }
342 
343  // Static. Set and unset the trigger when static_trigger is true.
344  if (uj_data.static_trigger) {
345  pentest_set_trigger_high();
346  }
347  asm volatile(NOP30);
348  asm volatile(NOP30);
349  asm volatile(NOP30);
350  if (uj_data.static_trigger) {
351  pentest_set_trigger_low();
352  }
353 
354  // Squeeze. Set and unset the trigger when squeeze_trigger is true.
355  uint32_t digest[kKmacTestVector.digest_len];
356  if (uj_data.squeeze_trigger) {
357  pentest_set_trigger_high();
358  }
359  TRY(dif_kmac_squeeze(&kmac, &kmac_operation_state, digest,
360  kKmacTestVector.digest_len, /*processed=*/NULL,
361  /*capacity=*/NULL));
362  if (uj_data.squeeze_trigger) {
363  pentest_set_trigger_low();
364  }
365 
366  // 2nd Squeeze. This shall enforce a permutation. Any injected fault will
367  // result in a completely different digest. Hence, allows for easy detection
368  // of an injected fault.
369  uint32_t digest_2nd[kKmacTestVector.digest_len];
370  TRY(dif_kmac_squeeze(&kmac, &kmac_operation_state, digest_2nd,
371  kKmacTestVector.digest_len, /*processed=*/NULL,
372  /*capacity=*/NULL));
373 
374  // Get registered alerts from alert handler.
375  reg_alerts = pentest_get_triggered_alerts();
376  // Get fatal and recoverable AST alerts from sensor controller.
377  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
378 
379  TRY(dif_kmac_end(&kmac, &kmac_operation_state));
380 
381  // Read ERR_STATUS register.
382  dif_rv_core_ibex_error_status_t codes;
383  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
384 
385  // Send the first 8 bytes of the digest and the alerts back to the host.
386  crypto_fi_kmac_digest_t uj_output;
387  uj_output.err_status = codes;
388  memcpy(uj_output.digest, (uint8_t *)digest, 8);
389  memcpy(uj_output.digest_2nd, (uint8_t *)digest_2nd, 8);
390  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
391  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
392  sizeof(sensor_alerts.alerts));
393  RESP_OK(ujson_serialize_crypto_fi_kmac_digest_t, uj, &uj_output);
394  return OK_STATUS();
395 }
396 
397 status_t handle_crypto_fi_kmac_state(ujson_t *uj) {
398  // Clear registered alerts in alert handler.
399  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
400  // Clear the AST recoverable alerts.
401  pentest_clear_sensor_recov_alerts();
402 
403  // Configure and write key to the KMAC block.
404  dif_kmac_operation_state_t kmac_operation_state;
405  TRY(dif_kmac_mode_kmac_start(&kmac, &kmac_operation_state,
406  kKmacTestVector.mode, 0, &kKmacTestVector.key,
407  NULL));
408  // Absorb.
409  TRY(dif_kmac_absorb(&kmac, &kmac_operation_state, kKmacTestVector.message,
410  kKmacTestVector.message_len, NULL));
411 
412  // Squeeze. Set and unset the trigger when squeeze_trigger is true.
413  uint32_t digest[kKmacTestVector.digest_len];
414  TRY(dif_kmac_squeeze(&kmac, &kmac_operation_state, digest,
415  kKmacTestVector.digest_len, /*processed=*/NULL,
416  /*capacity=*/NULL));
417 
418  // Static.
419  pentest_set_trigger_high();
420  asm volatile(NOP30);
421  asm volatile(NOP30);
422  asm volatile(NOP30);
423  pentest_set_trigger_low();
424 
425  // Get registered alerts from alert handler.
426  reg_alerts = pentest_get_triggered_alerts();
427  // Get fatal and recoverable AST alerts from sensor controller.
428  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
429 
430  // Read ERR_STATUS register.
431  dif_rv_core_ibex_error_status_t codes;
432  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
433 
434  // Send the Keccak state and the alerts back to the host.
435  crypto_fi_kmac_state_t uj_output;
436  // Read Keccak state shares
437  const mmio_region_t base = kmac.base_addr;
438  ptrdiff_t offset = KMAC_STATE_REG_OFFSET;
439  for (size_t i = 0; i < 200; i++) {
440  uj_output.share0[i] = mmio_region_read8(base, offset);
441  uj_output.share1[i] =
442  mmio_region_read8(base, offset + kDifKmacStateShareOffset);
443  offset += sizeof(uint8_t);
444  }
445  // Read error, digest, and alerts
446  uj_output.err_status = codes;
447  memcpy(uj_output.digest, (uint8_t *)digest, 8);
448  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
449  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
450  sizeof(sensor_alerts.alerts));
451 
452  RESP_OK(ujson_serialize_crypto_fi_kmac_state_t, uj, &uj_output);
453 
454  TRY(dif_kmac_end(&kmac, &kmac_operation_state));
455  return OK_STATUS();
456 }
457 
458 status_t handle_crypto_fi_sha256(ujson_t *uj) {
459  // Get the message.
460  crypto_fi_hmac_message_t uj_msg;
461  TRY(ujson_deserialize_crypto_fi_hmac_message_t(uj, &uj_msg));
462  // Get the test mode.
463  crypto_fi_hmac_mode_t uj_data;
464  TRY(ujson_deserialize_crypto_fi_hmac_mode_t(uj, &uj_data));
465  // Clear registered alerts in alert handler.
466  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
467 
468  if (uj_data.start_trigger) {
469  pentest_set_trigger_high();
470  }
471  TRY(dif_hmac_mode_sha256_start(&hmac, kHmacTransactionConfig));
472  if (uj_data.start_trigger) {
473  pentest_set_trigger_low();
474  }
475 
476  if (uj_data.msg_trigger) {
477  pentest_set_trigger_high();
478  }
479  TRY(hmac_testutils_push_message(&hmac, (char *)uj_msg.message,
480  sizeof(uj_msg.message)));
481  if (uj_data.msg_trigger) {
482  pentest_set_trigger_low();
483  }
484 
485  if (uj_data.process_trigger) {
486  pentest_set_trigger_high();
487  }
488  TRY(dif_hmac_process(&hmac));
489  if (uj_data.process_trigger) {
490  pentest_set_trigger_low();
491  }
492 
493  dif_hmac_digest_t digest;
494  if (uj_data.finish_trigger) {
495  pentest_set_trigger_high();
496  }
497  TRY(hmac_testutils_finish_polled(&hmac, &digest));
498  if (uj_data.finish_trigger) {
499  pentest_set_trigger_low();
500  }
501 
502  // Get registered alerts from alert handler.
503  reg_alerts = pentest_get_triggered_alerts();
504 
505  // Read ERR_STATUS register.
506  dif_rv_core_ibex_error_status_t codes;
507  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
508 
509  // Send the digest and the alerts back to the host.
510  crypto_fi_hmac_tag_t uj_output;
511  uj_output.err_status = codes;
512  memcpy(uj_output.tag, digest.digest, sizeof(uj_output.tag));
513  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
514  RESP_OK(ujson_serialize_crypto_fi_hmac_tag_t, uj, &uj_output);
515  return OK_STATUS();
516 }
517 
518 status_t handle_crypto_fi_shadow_reg_access(ujson_t *uj) {
519  // Clear registered alerts in alert handler.
520  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
521  // Clear the AST recoverable alerts.
522  pentest_clear_sensor_recov_alerts();
523 
524  crypto_fi_test_result_mult_t uj_output;
525 
526  // Values we want to write into the KMAC shadow registers during FI.
527  uint32_t ctrl_reg_kmac = KMAC_CFG_SHADOWED_REG_RESVAL;
528  ctrl_reg_kmac = bitfield_bit32_write(ctrl_reg_kmac,
529  KMAC_CFG_SHADOWED_MSG_ENDIANNESS_BIT, 1);
530  ctrl_reg_kmac = bitfield_bit32_write(
531  ctrl_reg_kmac, KMAC_CFG_SHADOWED_STATE_ENDIANNESS_BIT, 1);
532  ctrl_reg_kmac =
533  bitfield_bit32_write(ctrl_reg_kmac, KMAC_CFG_SHADOWED_SIDELOAD_BIT, 1);
534  ctrl_reg_kmac = bitfield_bit32_write(
535  ctrl_reg_kmac, KMAC_CFG_SHADOWED_ENTROPY_FAST_PROCESS_BIT, 0);
536  ctrl_reg_kmac =
537  bitfield_bit32_write(ctrl_reg_kmac, KMAC_CFG_SHADOWED_MSG_MASK_BIT, 1);
538  ctrl_reg_kmac = bitfield_bit32_write(ctrl_reg_kmac,
539  KMAC_CFG_SHADOWED_ENTROPY_READY_BIT, 0);
540  ctrl_reg_kmac = bitfield_bit32_write(
541  ctrl_reg_kmac, KMAC_CFG_SHADOWED_EN_UNSUPPORTED_MODESTRENGTH_BIT, 1);
542 
543  uint32_t ctrl_reg_kmac_addr =
544  TOP_EARLGREY_KMAC_BASE_ADDR + KMAC_CFG_SHADOWED_REG_OFFSET;
545 
546  pentest_set_trigger_high();
547  asm volatile(NOP10);
548  SHADOW_REG_ACCESS_10(ctrl_reg_kmac_addr, ctrl_reg_kmac)
549  SHADOW_REG_ACCESS_10(ctrl_reg_kmac_addr, ctrl_reg_kmac)
550  SHADOW_REG_ACCESS_10(ctrl_reg_kmac_addr, ctrl_reg_kmac)
551  asm volatile(NOP10);
552  pentest_set_trigger_low();
553 
554  // Get registered alerts from alert handler.
555  reg_alerts = pentest_get_triggered_alerts();
556  // Get fatal and recoverable AST alerts from sensor controller.
557  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
558 
559  // Read ERR_STATUS register.
560  dif_rv_core_ibex_error_status_t codes;
561  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
562 
563  // Read back KMAC shadow registers.
564  uint32_t ctrl_reg_kmac_read = abs_mmio_read32(TOP_EARLGREY_KMAC_BASE_ADDR +
565  KMAC_CFG_SHADOWED_REG_OFFSET);
566  uj_output.result[0] = ctrl_reg_kmac_read;
567  // Zeroize unused
568  uj_output.result[1] = 0;
569  uj_output.result[2] = 0;
570 
571  uj_output.err_status = codes;
572  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
573  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
574  sizeof(sensor_alerts.alerts));
575  RESP_OK(ujson_serialize_crypto_fi_test_result_mult_t, uj, &uj_output);
576 
577  return OK_STATUS();
578 }
579 
580 status_t handle_crypto_fi_shadow_reg_read(ujson_t *uj) {
581  // Clear registered alerts in alert handler.
582  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
583  // Clear the AST recoverable alerts.
584  pentest_clear_sensor_recov_alerts();
585 
586  crypto_fi_test_result_mult_t uj_output;
587 
588  // Initialize AES and KMAC with the default values.
589  uint32_t ctrl_reg_aes_init = AES_CTRL_SHADOWED_REG_RESVAL;
590  ctrl_reg_aes_init =
591  bitfield_field32_write(ctrl_reg_aes_init, AES_CTRL_SHADOWED_KEY_LEN_FIELD,
592  AES_CTRL_SHADOWED_KEY_LEN_VALUE_AES_128);
593  ctrl_reg_aes_init =
594  bitfield_field32_write(ctrl_reg_aes_init, AES_CTRL_SHADOWED_MODE_FIELD,
595  AES_CTRL_SHADOWED_MODE_VALUE_AES_ECB);
596  ctrl_reg_aes_init = bitfield_field32_write(
597  ctrl_reg_aes_init, AES_CTRL_SHADOWED_PRNG_RESEED_RATE_FIELD,
598  AES_CTRL_SHADOWED_PRNG_RESEED_RATE_VALUE_PER_64);
599  ctrl_reg_aes_init = bitfield_bit32_write(
600  ctrl_reg_aes_init, AES_CTRL_SHADOWED_SIDELOAD_BIT, true);
601  ctrl_reg_aes_init = bitfield_field32_write(
602  ctrl_reg_aes_init, AES_CTRL_SHADOWED_OPERATION_FIELD,
603  AES_CTRL_SHADOWED_OPERATION_VALUE_AES_DEC);
604  ctrl_reg_aes_init = bitfield_bit32_write(
605  ctrl_reg_aes_init, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
606  abs_mmio_write32_shadowed(
607  TOP_EARLGREY_AES_BASE_ADDR + AES_CTRL_SHADOWED_REG_OFFSET,
608  ctrl_reg_aes_init);
609  aes_spin_until(AES_STATUS_IDLE_BIT);
610 
611  uint32_t ctrl_reg_kmac_init = KMAC_CFG_SHADOWED_REG_RESVAL;
612  ctrl_reg_kmac_init = bitfield_bit32_write(
613  ctrl_reg_kmac_init, KMAC_CFG_SHADOWED_MSG_ENDIANNESS_BIT, 0);
614  ctrl_reg_kmac_init = bitfield_bit32_write(
615  ctrl_reg_kmac_init, KMAC_CFG_SHADOWED_STATE_ENDIANNESS_BIT, 0);
616  ctrl_reg_kmac_init = bitfield_bit32_write(ctrl_reg_kmac_init,
617  KMAC_CFG_SHADOWED_SIDELOAD_BIT, 0);
618  ctrl_reg_kmac_init = bitfield_bit32_write(
619  ctrl_reg_kmac_init, KMAC_CFG_SHADOWED_ENTROPY_FAST_PROCESS_BIT, 1);
620  ctrl_reg_kmac_init = bitfield_bit32_write(ctrl_reg_kmac_init,
621  KMAC_CFG_SHADOWED_MSG_MASK_BIT, 0);
622  ctrl_reg_kmac_init = bitfield_bit32_write(
623  ctrl_reg_kmac_init, KMAC_CFG_SHADOWED_ENTROPY_READY_BIT, 1);
624  ctrl_reg_kmac_init = bitfield_bit32_write(
625  ctrl_reg_kmac_init, KMAC_CFG_SHADOWED_EN_UNSUPPORTED_MODESTRENGTH_BIT, 0);
626  abs_mmio_write32_shadowed(
627  TOP_EARLGREY_KMAC_BASE_ADDR + KMAC_CFG_SHADOWED_REG_OFFSET,
628  ctrl_reg_kmac_init);
629 
630  pentest_set_trigger_high();
631  asm volatile(NOP30);
632  uint32_t ctrl_reg_aes_read = abs_mmio_read32(TOP_EARLGREY_AES_BASE_ADDR +
633  AES_CTRL_SHADOWED_REG_OFFSET);
634  uint32_t ctrl_reg_kmac_read = abs_mmio_read32(TOP_EARLGREY_KMAC_BASE_ADDR +
635  KMAC_CFG_SHADOWED_REG_OFFSET);
636  asm volatile(NOP30);
637  pentest_set_trigger_low();
638 
639  // Get registered alerts from alert handler.
640  reg_alerts = pentest_get_triggered_alerts();
641  // Get fatal and recoverable AST alerts from sensor controller.
642  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
643 
644  // Read ERR_STATUS register.
645  dif_rv_core_ibex_error_status_t codes;
646  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
647 
648  // Compare AES and KMAC values.
649  uj_output.result[0] = 0;
650  if (ctrl_reg_aes_read != ctrl_reg_aes_init) {
651  uj_output.result[0] = ctrl_reg_aes_read;
652  }
653 
654  uj_output.result[1] = 0;
655  if (ctrl_reg_kmac_read != ctrl_reg_kmac_init) {
656  uj_output.result[1] = ctrl_reg_kmac_read;
657  }
658 
659  uj_output.result[2] = 0;
660 
661  uj_output.err_status = codes;
662  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
663  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
664  sizeof(sensor_alerts.alerts));
665  RESP_OK(ujson_serialize_crypto_fi_test_result_mult_t, uj, &uj_output);
666 
667  return OK_STATUS();
668 }
669 
670 status_t handle_crypto_fi(ujson_t *uj) {
671  crypto_fi_subcommand_t cmd;
672  TRY(ujson_deserialize_crypto_fi_subcommand_t(uj, &cmd));
673  switch (cmd) {
674  case kCryptoFiSubcommandAes:
675  return handle_crypto_fi_aes(uj);
676  case kCryptoFiSubcommandInit:
677  return handle_crypto_fi_init(uj);
678  case kCryptoFiSubcommandKmac:
679  return handle_crypto_fi_kmac(uj);
680  case kCryptoFiSubcommandKmacState:
681  return handle_crypto_fi_kmac_state(uj);
682  case kCryptoFiSubcommandSha256:
683  return handle_crypto_fi_sha256(uj);
684  case kCryptoFiSubcommandShadowRegAccess:
685  return handle_crypto_fi_shadow_reg_access(uj);
686  case kCryptoFiSubcommandShadowRegRead:
687  return handle_crypto_fi_shadow_reg_read(uj);
688  default:
689  LOG_ERROR("Unrecognized Crypto FI subcommand: %d", cmd);
690  return INVALID_ARGUMENT();
691  }
692  return OK_STATUS();
693 }