Software APIs
pentest_lib.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/lib/pentest_lib.h"
6 
7 #include "hw/ip/aes/model/aes.h"
11 #include "sw/device/lib/base/csr.h"
14 #include "sw/device/lib/base/status.h"
18 #include "sw/device/lib/dif/dif_csrng_shared.h"
23 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
30 #include "sw/device/lib/runtime/irq.h"
32 #include "sw/device/lib/testing/pinmux_testutils.h"
33 #include "sw/device/lib/testing/rv_plic_testutils.h"
34 #include "sw/device/lib/testing/test_framework/check.h"
35 #include "sw/device/lib/testing/test_framework/ottf_isrs.h"
37 
38 #include "clkmgr_regs.h" // Generated
39 #include "csrng_regs.h" // Generated
41 #include "sensor_ctrl_regs.h" // Generated.
42 #include "sram_ctrl_regs.h" // Generated
43 
44 #if !OT_IS_ENGLISH_BREAKFAST
45 #include "sw/device/lib/crypto/drivers/otbn.h"
49 #include "sw/device/lib/testing/alert_handler_testutils.h"
50 #include "sw/device/lib/testing/entropy_testutils.h"
51 
52 #include "edn_regs.h" // Generated
53 #endif
54 
55 /**
56  * Bitfield for the trigger source.
57  *
58  * Bits 10 and 11 are used to select the trigger source. See chiplevel.sv.tpl
59  * for details.
60  */
61 static const bitfield_field32_t kTriggerSourceBitfield = {
62  .index = 10,
63  .mask = 0x3,
64 };
65 
66 enum {
67  /**
68  * Bit index of the hardware trigger gate signal for gating the hardware
69  * trigger from software.
70  *
71  * See chiplevel.sv.tpl for details.
72  */
73  kTriggerHwGateBitIndex = 9,
74  /**
75  * Bit index of the software trigger signal.
76  *
77  * See chiplevel.sv.tpl for details.
78  */
79  kTriggerSwBitIndex = 8,
80  /**
81  * RV timer settings.
82  */
83  kRvTimerComparator = 0,
84  kRvTimerHart = kTopEarlgreyPlicTargetIbex0,
85 };
86 
87 // By default, we use the precise, hardware-gated capture trigger.
88 static unsigned int trigger_bit_index = kTriggerHwGateBitIndex;
89 
90 static dif_gpio_t gpio;
91 static dif_pinmux_t pinmux;
92 static dif_rv_timer_t timer;
93 static dif_sensor_ctrl_t sensor_ctrl;
94 static dif_uart_t uart0;
95 static dif_uart_t uart1;
96 
97 #if !OT_IS_ENGLISH_BREAKFAST
98 static dif_alert_handler_t alert_handler;
99 static dif_csrng_t csrng;
100 static dif_edn_t edn0;
101 static dif_edn_t edn1;
102 static dif_lc_ctrl_t lc;
103 static dif_rv_plic_t plic;
104 static dif_rstmgr_t rstmgr;
105 #endif
106 
107 status_t pentest_configure_entropy_source_max_reseed_interval(void) {
108 #if !OT_IS_ENGLISH_BREAKFAST
109  const dif_csrng_t csrng = {
111  const dif_edn_t edn0 = {
113  const dif_edn_t edn1 = {
115 
116  TRY(entropy_testutils_stop_all());
117 
118  // Re-enable entropy src and csrng.
119  TRY(entropy_testutils_entropy_src_init());
120  TRY(dif_csrng_configure(&csrng));
121 
122  // Re-enable EDN0 in auto mode.
124  &edn0,
126  // EDN0 provides lower-quality entropy. Let one generate command
127  // return 8
128  // blocks, and reseed every 32 generates.
129  .instantiate_cmd =
130  {
131  .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
133  /*cmd_len=*/0,
134  /*generate_len=*/0),
135  .seed_material =
136  {
137  .len = 0,
138  },
139  },
140  .reseed_cmd =
141  {
142  .cmd = csrng_cmd_header_build(
143  kCsrngAppCmdReseed, kDifCsrngEntropySrcToggleEnable,
144  /*cmd_len=*/0, /*generate_len=*/0),
145  .seed_material =
146  {
147  .len = 0,
148  },
149  },
150  .generate_cmd =
151  {
152  // Generate 8 128-bit blocks.
153  .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
155  /*cmd_len=*/0,
156  /*generate_len=*/8),
157  .seed_material =
158  {
159  .len = 0,
160  },
161  },
162  // Reseed every 0xffffffff generates.
163  .reseed_interval = 0xffffffff,
164  }));
165 
166  // Re-enable EDN1 in auto mode.
168  &edn1,
170  // EDN1 provides highest-quality entropy. Let one generate command
171  // return 1 block, and reseed after every generate.
172  .instantiate_cmd =
173  {
174  .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
176  /*cmd_len=*/0,
177  /*generate_len=*/0),
178  .seed_material =
179  {
180  .len = 0,
181  },
182  },
183  .reseed_cmd =
184  {
185  .cmd = csrng_cmd_header_build(
186  kCsrngAppCmdReseed, kDifCsrngEntropySrcToggleEnable,
187  /*cmd_len=*/0, /*generate_len=*/0),
188  .seed_material =
189  {
190  .len = 0,
191  },
192  },
193  .generate_cmd =
194  {
195  // Generate 1 128-bit block.
196  .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
198  /*cmd_len=*/0,
199  /*generate_len=*/1),
200  .seed_material =
201  {
202  .len = 0,
203  },
204  },
205  // Reseed after every 0xffffffff generates.
206  .reseed_interval = 0xffffffff,
207  }));
208 #endif
209  return OK_STATUS();
210 }
211 
212 pentest_sensor_alerts_t pentest_get_sensor_alerts(void) {
213  pentest_sensor_alerts_t registered;
214  memset(registered.alerts, 0, sizeof(registered.alerts));
215  CHECK_DIF_OK(
216  dif_sensor_ctrl_get_fatal_events(&sensor_ctrl, &registered.alerts[0]));
217  CHECK_DIF_OK(
218  dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &registered.alerts[1]));
219  return registered;
220 }
221 
222 void pentest_clear_sensor_recov_alerts(void) {
223  for (size_t it = 0; it < SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS; it++) {
224  CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, it));
225  }
226 }
227 
228 pentest_registered_alerts_t pentest_get_triggered_alerts(void) {
229  pentest_registered_alerts_t registered;
230  memset(registered.alerts, 0, sizeof(registered.alerts));
231 
232 #if !OT_IS_ENGLISH_BREAKFAST
233  bool is_cause;
234  // Loop over all alert_cause regs
235  for (size_t alert = 0; alert < ALERT_HANDLER_PARAM_N_ALERTS; alert++) {
236  CHECK_DIF_OK(
237  dif_alert_handler_alert_is_cause(&alert_handler, alert, &is_cause));
238  if (is_cause) {
239  if (alert < 32) {
240  registered.alerts[0] |= (1 << alert);
241  } else if (alert < 64) {
242  registered.alerts[1] |= (1 << (alert - 32));
243  } else {
244  registered.alerts[2] |= (1 << (alert - 64));
245  }
246  }
247  }
248 
249  // Loop over all alert_cause regs.
250  for (dif_alert_handler_alert_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; i++) {
251  CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, i));
252  }
253 #endif
254 
255  return registered;
256 }
257 
258 void pentest_configure_alert_handler(void) {
259 #if !OT_IS_ENGLISH_BREAKFAST
260  irq_global_ctrl(true);
261  irq_external_ctrl(true);
262 
263  mmio_region_t base_addr =
265  CHECK_DIF_OK(dif_rv_plic_init(base_addr, &plic));
266 
268  CHECK_DIF_OK(dif_alert_handler_init(base_addr, &alert_handler));
269 
270  CHECK_DIF_OK(dif_rstmgr_init(
272 
273  dif_alert_handler_alert_t alerts[ALERT_HANDLER_PARAM_N_ALERTS];
274  dif_alert_handler_class_t alert_classes[ALERT_HANDLER_PARAM_N_ALERTS];
275 
276  // Enable all incoming alerts and configure them to classa.
277  for (dif_alert_handler_alert_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
278  alerts[i] = i;
279  alert_classes[i] = kDifAlertHandlerClassA;
280  }
281 
282  dif_alert_handler_escalation_phase_t esc_phases[] = {
284  .signal = 0,
285  .duration_cycles = 2000}};
286 
287  dif_alert_handler_class_config_t class_config = {
289  .accumulator_threshold = 0,
290  .irq_deadline_cycles = 10000,
291  .escalation_phases = esc_phases,
292  .escalation_phases_len = ARRAYSIZE(esc_phases),
293  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
294  };
295 
296  dif_alert_handler_class_config_t class_configs[] = {class_config};
297 
298  dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
299  dif_alert_handler_config_t config = {
300  .alerts = alerts,
301  .alert_classes = alert_classes,
302  .alerts_len = ARRAYSIZE(alerts),
303  .classes = classes,
304  .class_configs = class_configs,
305  .classes_len = ARRAYSIZE(class_configs),
306  .ping_timeout = 256,
307  };
308 
309  CHECK_STATUS_OK(alert_handler_testutils_configure_all(&alert_handler, config,
311  // Enables alert handler irq.
312  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
313  &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
314 #endif
315 }
316 
317 status_t pentest_read_device_id(uint32_t device_id[]) {
318 #if !OT_IS_ENGLISH_BREAKFAST
319  mmio_region_t lc_reg =
321  CHECK_DIF_OK(dif_lc_ctrl_init(lc_reg, &lc));
322 
323  dif_lc_ctrl_device_id_t lc_device_id;
324  CHECK_DIF_OK(dif_lc_ctrl_get_device_id(&lc, &lc_device_id));
325  memcpy(device_id, lc_device_id.data, 8 * sizeof(uint32_t));
326 #else
327  memset(device_id, 0, 8 * sizeof(uint32_t));
328 #endif
329 
330  return OK_STATUS();
331 }
332 
333 status_t pentest_configure_cpu(
334  bool disable_icache, bool disable_dummy_instr, bool enable_jittery_clock,
335  bool enable_sram_readback, bool *clock_jitter_locked, bool *clock_jitter_en,
336  bool *sram_main_readback_locked, bool *sram_ret_readback_locked,
337  bool *sram_main_readback_en, bool *sram_ret_readback_en) {
338  uint32_t cpuctrl_csr;
339  // Get current config.
340  CSR_READ(CSR_REG_CPUCTRL, &cpuctrl_csr);
341  // Disable the iCache.
342  if (disable_icache) {
343  cpuctrl_csr = bitfield_field32_write(
344  cpuctrl_csr, (bitfield_field32_t){.mask = 0x1, .index = 0}, 0);
345  }
346 
347  // Disable dummy instructions.
348  if (disable_dummy_instr) {
349  cpuctrl_csr = bitfield_field32_write(
350  cpuctrl_csr, (bitfield_field32_t){.mask = 0x1, .index = 2}, 0);
351  }
352 
353  // Write back config.
354  CSR_WRITE(CSR_REG_CPUCTRL, cpuctrl_csr);
355 
356  // Enable or disable the jittery clock.
357  dif_clkmgr_t clkmgr;
359  &clkmgr));
360 
361  TRY(dif_clkmgr_jitter_enable_is_locked(&clkmgr, clock_jitter_locked));
362  dif_toggle_t clock_jitter_state;
363  TRY(dif_clkmgr_jitter_get_enabled(&clkmgr, &clock_jitter_state));
364 
365  if (!*clock_jitter_locked) {
366  if (enable_jittery_clock) {
368  } else {
369  mmio_region_write32(clkmgr.base_addr, CLKMGR_JITTER_ENABLE_REG_OFFSET,
370  kMultiBitBool4False);
371  }
372  TRY(dif_clkmgr_jitter_get_enabled(&clkmgr, &clock_jitter_state));
373  }
374 
375  *clock_jitter_en = (clock_jitter_state == kDifToggleDisabled) ? false : true;
376 
377  // Enable or disable SRAM main and ret readback feature.
378  dif_sram_ctrl_t sram_ctrl_ret;
379  dif_sram_ctrl_t sram_ctrl_main;
380  TRY(dif_sram_ctrl_init(
382  &sram_ctrl_ret));
383  TRY(dif_sram_ctrl_init(
385  &sram_ctrl_main));
386 
387  dif_result_t ret_locked;
388  dif_result_t main_locked;
389  if (enable_sram_readback) {
390  ret_locked = dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleEnabled);
391  main_locked =
393  } else {
394  ret_locked = dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleDisabled);
395  main_locked =
397  }
398 
399  uint32_t ret_status =
401  SRAM_CTRL_READBACK_REG_OFFSET);
402  uint32_t main_status =
404  SRAM_CTRL_READBACK_REG_OFFSET);
405 
406  // Report the configuration.
407  *sram_main_readback_locked = (main_locked == kDifLocked) ? true : false;
408  *sram_ret_readback_locked = (ret_locked == kDifLocked) ? true : false;
409 
410  *sram_ret_readback_en = (ret_status == kMultiBitBool4True) ? true : false;
411  *sram_main_readback_en = (main_status == kMultiBitBool4True) ? true : false;
412 
413  return OK_STATUS();
414 }
415 
416 /**
417  * Initializes the UART peripheral.
418  */
419 static void pentest_init_uart(void) {
420  CHECK(kUartBaudrate <= UINT32_MAX, "kUartBaudrate must fit in uint32_t");
421  CHECK(kClockFreqPeripheralHz <= UINT32_MAX,
422  "kClockFreqPeripheralHz must fit in uint32_t");
423  const dif_uart_config_t uart_config = {
424  .baudrate = (uint32_t)kUartBaudrate,
425  .clk_freq_hz = (uint32_t)kClockFreqPeripheralHz,
426  .parity_enable = kDifToggleDisabled,
427  .parity = kDifUartParityEven,
428  .tx_enable = kDifToggleEnabled,
429  .rx_enable = kDifToggleEnabled,
430  };
431 
433  &uart0));
434  OT_DISCARD(dif_uart_configure(&uart0, uart_config));
435  base_uart_stdout(&uart0);
436 
437 #if !OT_IS_ENGLISH_BREAKFAST
439  &uart1));
440  OT_DISCARD(dif_uart_configure(&uart1, uart_config));
441 #endif
442 }
443 
444 /**
445  * Initializes the GPIO peripheral.
446  *
447  * @param trigger Trigger source.
448  */
449 static void pentest_init_gpio(pentest_trigger_source_t trigger) {
450  OT_DISCARD(
451  dif_gpio_init(mmio_region_from_addr(TOP_EARLGREY_GPIO_BASE_ADDR), &gpio));
452 
453  uint32_t select_mask =
454  bitfield_field32_write(0, kTriggerSourceBitfield, UINT32_MAX);
455  uint32_t enable_mask = bitfield_bit32_write(0, kTriggerHwGateBitIndex, true);
456  enable_mask = bitfield_bit32_write(enable_mask, kTriggerSwBitIndex, true);
457 
458  // Configure the pinmux to enable the GPIOs.
459  for (size_t i = 0; i < 32; ++i) {
460  if ((select_mask | enable_mask) & (1u << i)) {
462  dif_pinmux_index_t periph_io =
464  OT_DISCARD(dif_pinmux_input_select(&pinmux, periph_io, mio));
465 
467  periph_io = kTopEarlgreyPinmuxOutselGpioGpio0 + i;
468  OT_DISCARD(dif_pinmux_output_select(&pinmux, mio, periph_io));
469  }
470  }
471 
472  OT_DISCARD(dif_gpio_output_set_enabled_all(&gpio, select_mask | enable_mask));
473 
475  &gpio, select_mask,
476  bitfield_field32_write(0, kTriggerSourceBitfield, trigger)));
477 }
478 
479 /**
480  * Initializes the timer peripheral.
481  */
482 static void pentest_init_timer(void) {
483  OT_DISCARD(dif_rv_timer_init(
486  dif_rv_timer_tick_params_t tick_params;
488  kClockFreqPeripheralHz, kClockFreqCpuHz, &tick_params));
489  OT_DISCARD(dif_rv_timer_set_tick_params(&timer, kRvTimerHart, tick_params));
490  OT_DISCARD(dif_rv_timer_irq_set_enabled(
491  &timer, kDifRvTimerIrqTimerExpiredHart0Timer0, kDifToggleEnabled));
492  irq_timer_ctrl(true);
493  irq_global_ctrl(true);
494 }
495 
496 /**
497  * Initializes the CSRNG handle.
498  */
499 static void pentest_init_csrng(void) {
500 #if !OT_IS_ENGLISH_BREAKFAST
502  &csrng));
504  &csrng));
505 #endif
506 }
507 
508 static void pentest_init_sensor_ctrl(void) {
509 #if !OT_IS_ENGLISH_BREAKFAST
510  CHECK_DIF_OK(dif_sensor_ctrl_init(
512  &sensor_ctrl));
513 #endif
514 }
515 
516 /**
517  * Initializes the EDN handle.
518  */
519 static void pentest_init_edn(void) {
520 #if !OT_IS_ENGLISH_BREAKFAST
521  OT_DISCARD(
522  dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN0_BASE_ADDR), &edn0));
523 
524  OT_DISCARD(
525  dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN1_BASE_ADDR), &edn1));
526 #endif
527 }
528 
529 /**
530  * Override default Timer ISR.
531  *
532  * Disables the counter and clears pending interrupts.
533  */
534 void ottf_timer_isr(uint32_t *exc_info) {
535  // Return values of below functions are ignored to improve capture
536  // performance.
537  OT_DISCARD(dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart,
539  OT_DISCARD(dif_rv_timer_irq_acknowledge(
540  &timer, kDifRvTimerIrqTimerExpiredHart0Timer0));
541 }
542 
543 /**
544  * Disables the given peripherals to reduce noise during SCA.
545  *
546  * Care must be taken when disabling the entropy complex if a peripheral that
547  * depends on it will be used in SCA. E.g., We can disable the entropy complex
548  * when analyzing AES only because AES features a parameter to skip PRNG
549  * reseeding for SCA experiments. Without this parameter, AES would simply get
550  * stalled with a disabled entropy complex.
551  *
552  * @param disable Set of peripherals to disable.
553  */
554 void sca_disable_peripherals(pentest_peripherals_t disable) {
555 #if !OT_IS_ENGLISH_BREAKFAST
556  if (disable & kPentestPeripheralEdn) {
557  OT_DISCARD(dif_edn_stop(&edn0));
558  OT_DISCARD(dif_edn_stop(&edn1));
559  }
560  if (disable & kPentestPeripheralCsrng) {
561  OT_DISCARD(dif_csrng_stop(&csrng));
562  }
563  if (disable & kPentestPeripheralEntropy) {
564  dif_entropy_src_t entropy;
565  OT_DISCARD(dif_entropy_src_init(
568  }
569 #endif
570 
571  // Disable HMAC, KMAC, OTBN and USB clocks through CLKMGR DIF.
572  dif_clkmgr_t clkmgr;
573  OT_DISCARD(dif_clkmgr_init(
575 
576  if (disable & kPentestPeripheralAes) {
578  &clkmgr, CLKMGR_CLK_HINTS_CLK_MAIN_AES_HINT_BIT, kDifToggleDisabled));
579  }
580 #if !OT_IS_ENGLISH_BREAKFAST
581  if (disable & kPentestPeripheralHmac) {
583  &clkmgr, CLKMGR_CLK_HINTS_CLK_MAIN_HMAC_HINT_BIT, kDifToggleDisabled));
584  }
585 #endif
586  if (disable & kPentestPeripheralIoDiv4) {
588  &clkmgr, CLKMGR_CLK_ENABLES_CLK_IO_DIV4_PERI_EN_BIT,
590  }
591  if (disable & kPentestPeripheralIoDiv2) {
593  &clkmgr, CLKMGR_CLK_ENABLES_CLK_IO_DIV2_PERI_EN_BIT,
595  }
596  if (disable & kPentestPeripheralUsb) {
598  &clkmgr, CLKMGR_CLK_ENABLES_CLK_USB_PERI_EN_BIT, kDifToggleDisabled));
599  }
600  if (disable & kPentestPeripheralIo) {
602  &clkmgr, CLKMGR_CLK_ENABLES_CLK_IO_PERI_EN_BIT, kDifToggleDisabled));
603  }
604 
605 #if !OT_IS_ENGLISH_BREAKFAST
606  if (disable & kPentestPeripheralKmac) {
608  &clkmgr, CLKMGR_CLK_HINTS_CLK_MAIN_KMAC_HINT_BIT, kDifToggleDisabled));
609  }
610  if (disable & kPentestPeripheralOtbn) {
612  &clkmgr, CLKMGR_CLK_HINTS_CLK_MAIN_OTBN_HINT_BIT, kDifToggleDisabled));
613  }
614 #endif
615 }
616 
617 void pentest_init(pentest_trigger_source_t trigger,
618  pentest_peripherals_t enable) {
619  OT_DISCARD(dif_pinmux_init(
621  pinmux_testutils_init(&pinmux);
622  pentest_init_uart();
623  pentest_init_gpio(trigger);
624  pentest_init_timer();
625  pentest_init_csrng();
626  pentest_init_edn();
627  pentest_init_sensor_ctrl();
628  sca_disable_peripherals(~enable);
629 }
630 
631 const dif_uart_t *pentest_get_uart(void) { return &uart1; }
632 
633 void pentest_select_trigger_type(pentest_trigger_type_t trigger_type) {
634  if (trigger_type == kPentestTriggerTypeHwGated) {
635  trigger_bit_index = kTriggerHwGateBitIndex;
636  } else if (trigger_type == kPentestTriggerTypeSw) {
637  trigger_bit_index = kTriggerSwBitIndex;
638  }
639 }
640 
641 void pentest_set_trigger_high(void) {
642  OT_DISCARD(dif_gpio_write(&gpio, trigger_bit_index, true));
643 }
644 
645 void pentest_set_trigger_low(void) {
646  OT_DISCARD(dif_gpio_write(&gpio, trigger_bit_index, false));
647 }
648 
649 void pentest_call_and_sleep(sca_callee callee, uint32_t sleep_cycles,
650  bool sw_trigger, bool otbn) {
651  // Disable the IO_DIV4_PERI clock to reduce noise during the actual capture.
652  // This also disables the UART(s) and GPIO modules required for
653  // communication with the scope. Therefore, it has to be re-enabled after
654  // the capture.
655  dif_clkmgr_t clkmgr;
656  OT_DISCARD(dif_clkmgr_init(
658 
659  // Start timer to wake Ibex after the callee is done.
660  uint64_t current_time;
661  // Return values of below functions are ignored to improve capture
662  // performance.
663  OT_DISCARD(dif_rv_timer_counter_read(&timer, kRvTimerHart, &current_time));
664  OT_DISCARD(dif_rv_timer_arm(&timer, kRvTimerHart, kRvTimerComparator,
665  current_time + sleep_cycles));
666  OT_DISCARD(dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart,
668 
669  if (sw_trigger) {
670  pentest_set_trigger_high();
671  }
672 
673  callee();
674 
676 
677 #if !OT_IS_ENGLISH_BREAKFAST
678  if (otbn) {
679  otbn_busy_wait_for_done();
680  }
681 #endif
682 
683  if (sw_trigger) {
684  pentest_set_trigger_low();
685  }
686 
687  // Re-enable IO_DIV4_PERI clock to resume communication with the scope.
689  &clkmgr, CLKMGR_CLK_ENABLES_CLK_IO_DIV4_PERI_EN_BIT, kDifToggleEnabled));
690 }
691 
692 static uint32_t sca_lfsr_state_masking = 0xdeadbeef;
693 static uint32_t sca_lfsr_state_order = 0x99999999;
694 
695 void pentest_seed_lfsr(uint32_t seed, pentest_lfsr_context_t context) {
696  if (context == kPentestLfsrMasking) {
697  sca_lfsr_state_masking = seed;
698  }
699  if (context == kPentestLfsrOrder) {
700  sca_lfsr_state_order = seed;
701  }
702 }
703 
704 uint32_t pentest_next_lfsr(uint16_t num_steps, pentest_lfsr_context_t context) {
705  uint32_t sca_lfsr_state;
706  if (context == kPentestLfsrMasking) {
707  sca_lfsr_state = sca_lfsr_state_masking;
708  }
709  if (context == kPentestLfsrOrder) {
710  sca_lfsr_state = sca_lfsr_state_order;
711  }
712  const uint32_t lfsr_out = sca_lfsr_state;
713  for (size_t i = 0; i < num_steps; ++i) {
714  bool lfsr_bit = sca_lfsr_state & 0x00000001;
715  sca_lfsr_state = sca_lfsr_state >> 1;
716  if (lfsr_bit) {
717  sca_lfsr_state ^= 0x80000057;
718  }
719  }
720  if (context == kPentestLfsrMasking) {
721  sca_lfsr_state_masking = sca_lfsr_state;
722  }
723  if (context == kPentestLfsrOrder) {
724  sca_lfsr_state_order = sca_lfsr_state;
725  }
726  return lfsr_out;
727 }
728 
729 uint32_t pentest_linear_layer(uint32_t input) {
730  uint32_t output =
731  // output[7:0]
732  (((input >> 0) & 0x1) << 7) | (((input >> 6) & 0x1) << 6) |
733  (((input >> 11) & 0x1) << 5) | (((input >> 14) & 0x1) << 4) |
734  (((input >> 1) & 0x1) << 3) | (((input >> 7) & 0x1) << 2) |
735  (((input >> 10) & 0x1) << 1) | (((input >> 13) & 0x1) << 0) |
736  // output[15:8]
737  (((input >> 2) & 0x1) << 15) | (((input >> 4) & 0x1) << 14) |
738  (((input >> 9) & 0x1) << 13) | (((input >> 12) & 0x1) << 12) |
739  (((input >> 3) & 0x1) << 11) | (((input >> 5) & 0x1) << 10) |
740  (((input >> 8) & 0x1) << 9) | (((input >> 15) & 0x1) << 8) |
741  // output[23:16]
742  (((input >> 16) & 0x1) << 23) | (((input >> 22) & 0x1) << 22) |
743  (((input >> 27) & 0x1) << 21) | (((input >> 30) & 0x1) << 20) |
744  (((input >> 17) & 0x1) << 19) | (((input >> 23) & 0x1) << 18) |
745  (((input >> 26) & 0x1) << 17) | (((input >> 29) & 0x1) << 16) |
746  // output[31:24]
747  (((input >> 18) & 0x1) << 31) | (((input >> 20) & 0x1) << 30) |
748  (((input >> 25) & 0x1) << 29) | (((input >> 28) & 0x1) << 28) |
749  (((input >> 19) & 0x1) << 27) | (((input >> 21) & 0x1) << 26) |
750  (((input >> 24) & 0x1) << 25) | (((input >> 31) & 0x1) << 24);
751 
752  return output;
753 }
754 
755 uint32_t pentest_non_linear_layer(uint32_t input) {
756  uint32_t output;
757  if (input != 0) {
758  // Perform the AES S-Box look ups bytewise.
759  output = (uint32_t)(sbox[(input >> 24) & 0xFF] << 24) |
760  (uint32_t)(sbox[(input >> 16) & 0xFF] << 16) |
761  (uint32_t)(sbox[(input >> 8) & 0xFF] << 8) | sbox[input & 0xFF];
762  } else {
763  output = input;
764  }
765 
766  return output;
767 }