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