Software APIs
pentest_lib.h
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 #ifndef OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_
6 #define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_
7 
9 #include "sw/device/lib/ujson/ujson.h"
10 #include "sw/device/tests/penetrationtests/json/pentest_lib_commands.h"
11 
12 // NOP macros used in different FI tests.
13 #define NOP1 "nop\n"
14 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
15 #define NOP30 NOP10 NOP10 NOP10
16 #define NOP100 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10
17 #define NOP1000 \
18  NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100
19 
20 // Optimized (in terms of number of cycles) trigger high function.
21 // Consists of:
22 // - 10 NOPS to make sure that the previous code execution has finished
23 // - Disassembled `dif_gpio_write(&gpio, kTriggerSwBitIndex, true)`
24 // - 10 NOPS to give the trigger time to raise
25 // Use with caution as the trigger pin index could change.
26 #define PENTEST_ASM_TRIGGER_HIGH \
27  asm volatile(NOP10); \
28  asm volatile("lui a0, 0x1000;"); \
29  asm volatile("addi a0, a0, 256;"); \
30  asm volatile("lui a1, 0x40040;"); \
31  asm volatile("sw a0, 24(a1);"); \
32  asm volatile(NOP10);
33 
34 // Optimized (in terms of number of cycles) trigger low function.
35 // Consists of:
36 // - 10 NOPS to make sure that the previous code execution has finished
37 // - Disassembled `dif_gpio_write(&gpio, kTriggerSwBitIndex, false)`
38 // - 10 NOPS to give the trigger time to fall
39 // Use with caution as the trigger pin index could change.
40 #define PENTEST_ASM_TRIGGER_LOW \
41  asm volatile(NOP10); \
42  asm volatile("lui a0, 0x1000;"); \
43  asm volatile("lui a1, 0x40040;"); \
44  asm volatile("sw a0, 24(a1);"); \
45  asm volatile(NOP10);
46 
47 typedef struct pentest_registered_alerts {
48  uint32_t alerts[3];
50 
51 typedef struct pentest_sensor_alerts {
52  uint32_t alerts[2];
54 
55 /**
56  * Trigger sources.
57  *
58  * The trigger signal for a peripheral is based on its clkmgr_aon_idle signal.
59  * These values must match the values in chiplevel.sv.tpl.
60  */
61 typedef enum pentest_trigger_source {
62  /**
63  * Use AES for capture trigger.
64  *
65  * The trigger signal will go high 320 cycles after `dif_aes_trigger()` is
66  * called and remain high until the operation is complete.
67  */
68  kPentestTriggerSourceAes = 0,
69  /**
70  * Use HMAC for capture trigger.
71  */
72  kPentestTriggerSourceHmac = 1,
73  /**
74  * Use KMAC for capture trigger.
75  */
76  kPentestTriggerSourceKmac = 2,
77  /**
78  * Use OTBN for capture trigger.
79  */
80  kPentestTriggerSourceOtbn = 3,
81 } pentest_trigger_source_t;
82 
83 /**
84  * Trigger type.
85  */
86 typedef enum pentest_trigger_type {
87  /**
88  * Use the precise hardware capture trigger gateable by software. If selected,
89  * the actual capture trigger is generated based on the clkmgr_aon_idle signal
90  * of the peripheral corresponding to selected trigger source.
91  *
92  * Note that this is available on FPGA only.
93  */
94  kPentestTriggerTypeHwGated = 0,
95  /**
96  * Use the fully software controlled capture trigger. If selected, the
97  * configured trigger source is not relevant.
98  */
99  kPentestTriggerTypeSw = 1,
100 } pentest_trigger_type_t;
101 
102 /**
103  * Peripherals.
104  *
105  * Constants below are bitmasks that can be used to specify a set of
106  * peripherals.
107  *
108  * See also: `pentest_peripherals_t`.
109  */
110 typedef enum pentest_peripheral {
111  /**
112  * EDN.
113  */
114  kPentestPeripheralEdn = 1 << 0,
115  /**
116  * CSRNG.
117  */
118  kPentestPeripheralCsrng = 1 << 1,
119  /**
120  * Entropy source.
121  */
122  kPentestPeripheralEntropy = 1 << 2,
123  /**
124  * AES.
125  */
126  kPentestPeripheralAes = 1 << 3,
127  /**
128  * HMAC.
129  */
130  kPentestPeripheralHmac = 1 << 4,
131  /**
132  * KMAC.
133  */
134  kPentestPeripheralKmac = 1 << 5,
135  /**
136  * OTBN.
137  */
138  kPentestPeripheralOtbn = 1 << 6,
139  /**
140  * Peripherals using the IO_DIV4_PERI clock (UART, GPIO, I2C, SPI Dev, ...)
141  */
142  kPentestPeripheralIoDiv4 = 1 << 7,
143  /**
144  * Peripherals using the IO_DIV2_PERI clock (SPI Host 1)
145  */
146  kPentestPeripheralIoDiv2 = 1 << 8,
147  /**
148  * USB.
149  */
150  kPentestPeripheralUsb = 1 << 9,
151  /**
152  * Peripherals using the IO_PERI clock (SPI Host 0)
153  */
154  kPentestPeripheralIo = 1 << 10,
155 } pentest_peripheral_t;
156 
157 /**
158  * A set of peripherals.
159  *
160  * This type is used for specifying which peripherals should be enabled when
161  * calling `pentest_init()`. Remaining peripherals will be disabled to reduce
162  * noise during SCA.
163  *
164  * See also: `pentest_peripheral_t`, `pentest_init()`.
165  */
166 typedef uint32_t pentest_peripherals_t;
167 
168 /**
169  * A set of contexts for SW LFSR
170  *
171  * This type is used for specifying the context of the LFSR, with each context
172  * corresponding to a different state variable
173  */
174 typedef enum pentest_lfsr_context {
175  /**
176  * PRNG used for initial data sharing
177  */
178  kPentestLfsrMasking = 0,
179  /**
180  * PRNG used for determining the order of fixed and random measurements
181  */
182  kPentestLfsrOrder = 1,
183 
184 } pentest_lfsr_context_t;
185 
186 /**
187  * Configures the entropy complex for OTBN tests.
188  *
189  * Similar to entropy_testutils_auto_mode_init(), this function inits the
190  * entropy complex. However, in comparison to the function available in the
191  * testutils, this function maximizes the reseed intervall to 0xffffffff.
192  * This is necessary to guarantee a fixed trigger window for OTBN tests.
193  *
194  * @return OK or error.
195  */
196 status_t pentest_configure_entropy_source_max_reseed_interval(void);
197 
198 /**
199  * Returns the registered alerts in the sensor controller.
200  *
201  * This function reads out the recov_alert and fatal_alert registers of the
202  * sensor controller. This controller collects the alerts of the AST.
203  *
204  * @return A struct containing which of the alerts were triggered during the
205  * test.
206  */
207 pentest_sensor_alerts_t pentest_get_sensor_alerts(void);
208 
209 /**
210  * Clears the recoverable AST alerts in the sensor controller.
211  */
212 void pentest_clear_sensor_recov_alerts(void);
213 
214 /**
215  * Returns the registered alerts.
216  *
217  * If a fault injection triggered an alert, this function returns the alert ID
218  * back to the host. Afterwards, the alert is cleared.
219  *
220  * @return A struct containing which of the alerts were triggered during the
221  * test.
222  */
223 pentest_registered_alerts_t pentest_get_triggered_alerts(void);
224 
225 /**
226  * Configures the alert handler for FI.
227  *
228  * Register all alerts and let them escalate to Phase0 only.
229  */
230 void pentest_configure_alert_handler(void);
231 
232 /**
233  * Reads the device ID from the LC.
234  *
235  * Can be used to categorize different SCA and FI runs.
236  *
237  * @param device_id A buffer available to store the device id.
238  * @return OK or error.
239  */
240 status_t pentest_read_device_id(uint32_t device_id[]);
241 
242 /**
243  * Configures CPU for SCA and FI penetration tests.
244  *
245  * If disable_icache is True, this functions disables the instruction cache. If
246  * disable_icache is False, the instruction cache config remains at
247  * enabled/disabled based on the ROM configuration. This implies that the iCache
248  * could be disabled even though disable_icache is False.
249  *
250  * If disable_dummy_instr is True, this functions disables the dummy
251  * instructions. If disable_dummy_instr is False, the dummy instruction config
252  * remains at the original config that was set in the ROM. This implies that
253  * dummy instructions could disabled even though disable_dummy_instr is False.
254  *
255  * For enable_jittery_clock, the function first checks if the write protection
256  * for this register is enabled. Then, by setting enable_jittery_clock True or
257  * False, the jittery clock is enabled or disabled. When regwen is active, no
258  * change happens.
259  *
260  * For enable_sram_readback, the function first checks if the write protection
261  * for this register is enabled. Then, by setting enable_sram_readback True or
262  * False, the SRAM readback feature for the main and ret SRAM iss enabled or
263  * disabled. When regwen is active, no change happens.
264  *
265  * @param disable_icache Disable the instruction cache.
266  * @param disable_dummy_instr Disable the dummy instructions.
267  * @param enable_jittery_clock: Enable/disable the jittery clock.
268  * @param enable_sram_readback: Enable/disable the SRAM readback feature.
269  * @param clock_jitter_locked: Jittery clock register is locked.
270  * @param clock_jitter_en: Jittery clock feature is enabled.
271  * @param sram_main_readback_locked: SRAM main readback register is locked.
272  * @param sram_ret_readback_locked: SRAM ret readback register is locked.
273  * @param sram_main_readback_en: SRAM main readback feature is enabled.
274  * @param sram_ret_readback_en: SRAM ret readback feature is enabled.
275  * @return OK or error.
276  */
277 status_t pentest_configure_cpu(
278  bool disable_icache, bool disable_dummy_instr, bool enable_jittery_clock,
279  bool enable_sram_readback, bool *clock_jitter_locked, bool *clock_jitter_en,
280  bool *sram_main_readback_locked, bool *sram_ret_readback_locked,
281  bool *sram_main_readback_en, bool *sram_ret_readback_en);
282 
283 /**
284  * Initializes the peripherals (pinmux, uart, gpio, and timer) used by SCA code.
285  *
286  * @param trigger Peripheral to use for the trigger signal.
287  * @param enable Set of peripherals to enable. Remaining peripherals will
288  * be disabled to reduce noise during SCA.
289  */
290 void pentest_init(pentest_trigger_source_t trigger,
291  pentest_peripherals_t enable);
292 
293 /**
294  * Returns a handle to the intialized UART device.
295  *
296  * @return Handle to the initialized UART device.
297  */
298 const dif_uart_t *pentest_get_uart(void);
299 
300 /**
301  * Select the capture trigger type.
302  *
303  * @param trigger_type The trigger type to select.
304  */
305 void pentest_select_trigger_type(pentest_trigger_type_t trigger_type);
306 
307 /**
308  * Sets capture trigger high.
309  *
310  * The actual trigger signal used for capture is a combination (logical AND) of:
311  * - the trigger gate enabled here, and
312  * - the busy signal of the peripheral of interest.
313  */
314 void pentest_set_trigger_high(void);
315 
316 /**
317  * Sets capture trigger low.
318  */
319 void pentest_set_trigger_low(void);
320 
321 /**
322  * Functions called by `pentest_call_and_sleep()` must conform to this
323  * prototype.
324  */
325 typedef void (*sca_callee)(void);
326 
327 /**
328  * Calls the given function and puts Ibex to sleep.
329  *
330  * This function can be used to minimize noise while capturing power traces for
331  * side-channel attacks, in which case `callee` would trigger the operation of
332  * interest, typically a crypto operation, on the target device.
333  *
334  * @param callee Function to call before putting Ibex to sleep.
335  * @param sleep_cycles Number of cycles to sleep.
336  * @param sw_trigger Raise trigger before calling the target function.
337  * @param otbn Wait until OTBN execution has finished. Not supported in
338  * ENGLISH_BREAKFAST.
339  */
340 void pentest_call_and_sleep(sca_callee callee, uint32_t sleep_cycles,
341  bool sw_trigger, bool otbn);
342 
343 /**
344  * Seeds the software LFSR usable e.g. for key masking.
345  *
346  * This functions seeds the Galois XOR type LFSR with the provided seed value.
347  * Note that the LFSR itself has very low diffusion.
348  *
349  * @param seed The new seed value.
350  * @param context Specifies which LFSR to seed.
351  */
352 void pentest_seed_lfsr(uint32_t seed, pentest_lfsr_context_t context);
353 
354 /**
355  * Steps the software LFSR usable e.g. for key masking `num_steps` times.
356  *
357  * This function steps the Galois XOR type LFSR n times. Note that the LFSR
358  * itself has very low diffusion. To improve the statistical properties, the
359  * multiple steps can be run. For example, by running 32 steps it can be
360  * ensured that each state bit depends on at least two previous state bits.
361  *
362  * @param num_steps The number of steps to run.
363  * @param context Specifies which LFSR to run.
364 
365  * @return The current state of the LFSR.
366  */
367 uint32_t pentest_next_lfsr(uint16_t num_steps, pentest_lfsr_context_t context);
368 
369 /**
370  * Applies a linear layer.
371  *
372  * This function feeds the input through a linear permutation layer. This is
373  * suitable to ensure 1) that adjacent output bits of the software LFSR do not
374  * go into the same S-Box (see `pentest_non_linear_layer()`) and 2) that the
375  * output of S-Box(n) is not always going to be equal to the output of
376  * S-Box(n+1) in the subsequent cycle. For details on how this can be achieved,
377  * refer to the corresponding hardware implementation in
378  * hw/ip/prim/rtl/prim_lfsr.sv.
379  *
380  * @param input The input value.
381  *
382  * @return The output of the linear layer.
383  *
384  */
385 uint32_t pentest_linear_layer(uint32_t input);
386 
387 /**
388  * Applies a non-linear layer.
389  *
390  * This function feeds the input through a non-linear layer. It is suitable to
391  * improve the statistical properties of the software LFSR usable for key
392  * masking, see `pentest_seed_lfsr()` and `pentest_next_lfsr()`. Internally, a
393  * LUT-based AES S-Box is applied to the invididual bytes of the input word.
394  *
395  * In addition, the ouput bytes are XORed with the sbox[0]. This is useful to
396  * ensure an all-zero seed (used to switch off key masking) also results in an
397  * all-zero output of the non-linear layer.
398  *
399  * @param input The input value.
400  *
401  * @return The output of the non-linear layer.
402  *
403  */
404 uint32_t pentest_non_linear_layer(uint32_t input);
405 
406 /**
407  * Read alert information.
408  *
409  * This function reads the reset reason from the reason manager as well as the
410  * crash dump from the reset manager. Note that on a POR this information is NOT
411  * saved within the reset manager.
412  *
413  * @param uj An initialized uJSON context.
414  * @return OK or error.
415  */
416 status_t pentest_read_rstmgr_alert_info(ujson_t *uj);
417 
418 #endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_