Software APIs
ibex_fi.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_FI_IBEX_FI_H_
6 #define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_FI_IBEX_FI_H_
7 
8 #include "sw/device/lib/base/status.h"
9 #include "sw/device/lib/ujson/ujson.h"
10 
11 /**
12  * ibex.fi.address_translation command handler.
13  *
14  * This FI penetration tests executes the following instructions:
15  * - Configure the address translation for slot 0 and 1.
16  * - increment_100x1 gets remapped to increment_100x10 and
17  * increment_100x10 gets remapped to increment_100x1 using the address
18  * translation unit
19  * - Set the trigger.
20  * - Add 100 NOPs to delay the trigger.
21  * - Execute the increment_100x10 function.
22  * - Unset the trigger.
23  * - Check if instead of the expected function the target function was called.
24  * - Return the values over UART.
25  *
26  * Faults are injected during the trigger_high & trigger_low.
27  * It needs to be ensured that the compiler does not optimize this code.
28  *
29  * @param uj An initialized uJSON context.
30  * @return OK or error.
31  */
32 status_t handle_ibex_fi_address_translation(ujson_t *uj);
33 
34 /**
35  * ibex.fi.address_translation_config command handler.
36  *
37  * This FI penetration tests executes the following instructions:
38  * - Configure the address translation for DMEM and IMEM.
39  * - Set the trigger.
40  * - Add 1000 NOPs.
41  * - Unset the trigger.
42  * - Read address translation config.
43  * - Compare the values.
44  * - Return the values over UART.
45  *
46  * Faults are injected during the trigger_high & trigger_low.
47  * It needs to be ensured that the compiler does not optimize this code.
48  *
49  * @param uj An initialized uJSON context.
50  * @return OK or error.
51  */
52 status_t handle_ibex_fi_address_translation_config(ujson_t *uj);
53 
54 /**
55  * ibex.fi.char.conditional_branch_beq command handler.
56  *
57  * This FI penetration tests executes the following instructions:
58  * - Add 10 NOPs to delay the trigger
59  * - Execute 30 beq instructions. Without a fault, the branch is not taken.
60  * In the faulty case, a branch redirects the control-flow to the label
61  * endfitestfaultybeq where two register values are set to a pattern that can
62  * be detected at the host.
63  * - Return the values over UART.
64  * Faults are injected during the trigger_high & trigger_low.
65  * It needs to be ensured that the compiler does not optimize this code.
66  *
67  * @param uj An initialized uJSON context.
68  * @return OK or error.
69  */
70 status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj);
71 
72 /**
73  * ibex.fi.char.conditional_branch_bge command handler.
74  *
75  * This FI penetration tests executes the following instructions:
76  * - Add 10 NOPs to delay the trigger
77  * - Execute 30 bge instructions. Without a fault, the branch is not taken.
78  * In the faulty case, a branch redirects the control-flow to the label
79  * endfitestfaultybge where two register values are set to a pattern that can
80  * be detected at the host.
81  * - Return the values over UART.
82  * Faults are injected during the trigger_high & trigger_low.
83  * It needs to be ensured that the compiler does not optimize this code.
84  *
85  * @param uj An initialized uJSON context.
86  * @return OK or error.
87  */
88 status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj);
89 
90 /**
91  * ibex.fi.char.conditional_branch_bgeu command handler.
92  *
93  * This FI penetration tests executes the following instructions:
94  * - Add 10 NOPs to delay the trigger
95  * - Execute 30 bgeu instructions. Without a fault, the branch is not taken.
96  * In the faulty case, a branch redirects the control-flow to the label
97  * endfitestfaultybgeu where two register values are set to a pattern that can
98  * be detected at the host.
99  * - Return the values over UART.
100  * Faults are injected during the trigger_high & trigger_low.
101  * It needs to be ensured that the compiler does not optimize this code.
102  *
103  * @param uj An initialized uJSON context.
104  * @return OK or error.
105  */
106 status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj);
107 
108 /**
109  * ibex.fi.char.conditional_branch_blt command handler.
110  *
111  * This FI penetration tests executes the following instructions:
112  * - Add 10 NOPs to delay the trigger
113  * - Execute 30 blt instructions. Without a fault, the branch is not taken.
114  * In the faulty case, a branch redirects the control-flow to the label
115  * endfitestfaultyblt where two register values are set to a pattern that can
116  * be detected at the host.
117  * - Return the values over UART.
118  * Faults are injected during the trigger_high & trigger_low.
119  * It needs to be ensured that the compiler does not optimize this code.
120  *
121  * @param uj An initialized uJSON context.
122  * @return OK or error.
123  */
124 status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj);
125 
126 /**
127  * ibex.fi.char.conditional_branch_bltu command handler.
128  *
129  * This FI penetration tests executes the following instructions:
130  * - Add 10 NOPs to delay the trigger
131  * - Execute 30 bltu instructions. Without a fault, the branch is not taken.
132  * In the faulty case, a branch redirects the control-flow to the label
133  * endfitestfaultybltu where two register values are set to a pattern that can
134  * be detected at the host.
135  * - Return the values over UART.
136  * Faults are injected during the trigger_high & trigger_low.
137  * It needs to be ensured that the compiler does not optimize this code.
138  *
139  * @param uj An initialized uJSON context.
140  * @return OK or error.
141  */
142 status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj);
143 
144 /**
145  * ibex.fi.char.conditional_branch_bne command handler.
146  *
147  * This FI penetration tests executes the following instructions:
148  * - Add 10 NOPs to delay the trigger
149  * - Execute 30 bne instructions. Without a fault, the branch is not taken.
150  * In the faulty case, a branch redirects the control-flow to the label
151  * endfitestfaultybne where two register values are set to a pattern that can
152  * be detected at the host.
153  * - Return the values over UART.
154  * Faults are injected during the trigger_high & trigger_low.
155  * It needs to be ensured that the compiler does not optimize this code.
156  *
157  * @param uj An initialized uJSON context.
158  * @return OK or error.
159  */
160 status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj);
161 
162 /**
163  * ibex.fi.char.csr_read command handler.
164  *
165  * This FI penetration tests executes the following instructions:
166  * - Write reference values into CSRs.
167  * - Set the trigger.
168  * - Add 10 NOPs to delay the trigger
169  * - Read values from CSRs.
170  * - Unset the trigger.
171  * - Compare the values.
172  * - Return the values over UART.
173  *
174  * Faults are injected during the trigger_high & trigger_low.
175  * It needs to be ensured that the compiler does not optimize this code.
176  *
177  * @param uj An initialized uJSON context.
178  * @return OK or error.
179  */
180 status_t handle_ibex_fi_char_csr_read(ujson_t *uj);
181 
182 /**
183  * ibex.fi.char.csr_write command handler.
184  *
185  * This FI penetration tests executes the following instructions:
186  * - Init x5 with reference value.
187  * - Set the trigger.
188  * - Add 10 NOPs to delay the trigger
189  * - Repeat:
190  * - Write x5 into CSR.
191  * - Read CSR into x5
192  * - Unset the trigger.
193  * - Compare x5 with reference value.
194  * - Return the values over UART.
195  *
196  * Faults are injected during the trigger_high & trigger_low.
197  * It needs to be ensured that the compiler does not optimize this code.
198  *
199  * @param uj An initialized uJSON context.
200  * @return OK or error.
201  */
202 status_t handle_ibex_fi_char_csr_write(ujson_t *uj);
203 
204 /**
205  * ibex.fi.char.flash_read command handler.
206  *
207  * This FI penetration tests executes the following instructions:
208  * - Write reference values into flash.
209  * - Set the trigger.
210  * - Add 10 NOPs to delay the trigger
211  * - Read values from flash.
212  * - Unset the trigger.
213  * - Compare the values.
214  * - Return the values over UART.
215  *
216  * Faults are injected during the trigger_high & trigger_low.
217  * It needs to be ensured that the compiler does not optimize this code.
218  *
219  * @param uj An initialized uJSON context.
220  * @return OK or error.
221  */
222 status_t handle_ibex_fi_char_flash_read(ujson_t *uj);
223 
224 /**
225  * ibex.fi.char.flash_write command handler.
226  *
227  * This FI penetration tests executes the following instructions:
228  * - Set the trigger.
229  * - Add 10 NOPs to delay the trigger
230  * - Write 32 values into flash.
231  * - Unset the trigger.
232  * - Read back values and compare.
233  * - Return the values over UART.
234  *
235  * Faults are injected during the trigger_high & trigger_low.
236  * It needs to be ensured that the compiler does not optimize this code.
237  *
238  * @param uj An initialized uJSON context.
239  * @return OK or error.
240  */
241 status_t handle_ibex_fi_char_flash_write(ujson_t *uj);
242 
243 /**
244  * ibex.fi.char.hardened_check_eq_complement_branch command handler.
245  *
246  * Same as ibex.fi.char.hardened_check_eq_unimp but with an additional
247  * complement branch to the unimp instruction.
248  *
249  * Faults are injected during the trigger_high & trigger_low.
250  *
251  * @param uj An initialized uJSON context.
252  * @return OK or error.
253  */
254 status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj);
255 
256 /**
257  * ibex.fi.char.hardened_check_eq_unimp command handler.
258  *
259  * Inject faults during a hardened check is executed. As the values to compare
260  * are not equal, this test is expected to crash the system.
261  *
262  * Faults are injected during the trigger_high & trigger_low.
263  *
264  * @param uj An initialized uJSON context.
265  * @return OK or error.
266  */
267 status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj);
268 
269 /**
270  * ibex.fi.char.hardened_check_eq_2_unimps command handler.
271  *
272  * Same as ibex.fi.char.hardened_check_eq_unimp but with 2 unimp instructions.
273  *
274  * Faults are injected during the trigger_high & trigger_low.
275  *
276  * @param uj An initialized uJSON context.
277  * @return OK or error.
278  */
279 status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj);
280 
281 /**
282  * ibex.fi.char.hardened_check_eq_3_unimps command handler.
283  *
284  * Same as ibex.fi.char.hardened_check_eq_unimp but with 3 unimp instructions.
285  *
286  * Faults are injected during the trigger_high & trigger_low.
287  *
288  * @param uj An initialized uJSON context.
289  * @return OK or error.
290  */
291 status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj);
292 
293 /**
294  * ibex.fi.char.hardened_check_eq_4_unimps command handler.
295  *
296  * Same as ibex.fi.char.hardened_check_eq_unimp but with 4 unimp instructions.
297  *
298  * Faults are injected during the trigger_high & trigger_low.
299  *
300  * @param uj An initialized uJSON context.
301  * @return OK or error.
302  */
303 status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj);
304 
305 /**
306  * ibex.fi.char.hardened_check_eq_5_unimps command handler.
307  *
308  * Same as ibex.fi.char.hardened_check_eq_unimp but with 5 unimp instructions.
309  *
310  * Faults are injected during the trigger_high & trigger_low.
311  *
312  * @param uj An initialized uJSON context.
313  * @return OK or error.
314  */
315 status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj);
316 
317 /**
318  * ibex.fi.char.mem_op_loop command handler.
319  *
320  * This FI penetration tests executes the following instructions:
321  * - Add 100 NOPs to delay the trigger
322  * - 10000 iterations with a for loop:
323  * - Load loop_counter1 value into x5: lw x5, (&loop_counter1)
324  * - Increment loop counter1: addi x5, x5, 1
325  * - Store loop counter1 back to loop_counter1: sw x5, (&loop_counter1)
326  * - Load loop_counter2 value into x6: lw x6, (&loop_counter2)
327  * - Decrement loop counter2: addi x6, x6, -1
328  * - Store loop counter2 back to loop_counter2: sw x6, (&loop_counter2)
329  * - Return the values over UART.
330  * Faults are injected during the trigger_high & trigger_low.
331  * It needs to be ensured that the compiler does not optimize this code.
332  *
333  * @param uj An initialized uJSON context.
334  * @return OK or error.
335  */
336 status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj);
337 
338 /**
339  * ibex.fi.char.register_file command handler.
340  *
341  * This FI penetration test executes the following instructions:
342  * - Initialize temp. registers with reference values
343  * - Execute 1000 NOPs
344  * - Read back temp. register values and compare against reference values
345  *
346  * Faults are injected during the trigger_high & trigger_low.
347  * It needs to be ensured that the compiler does not optimize this code.
348  *
349  * @param uj An initialized uJSON context.
350  * @return OK or error.
351  */
352 status_t handle_ibex_fi_char_register_file(ujson_t *uj);
353 
354 /**
355  * ibex.fi.char.register_file_read command handler.
356  *
357  * This FI penetration test executes the following instructions:
358  * - Initialize temp. registers with reference values
359  * - or reg reg reg
360  * - Compare against reference values
361  *
362  * Faults are injected during the trigger_high & trigger_low.
363  * It needs to be ensured that the compiler does not optimize this code.
364  *
365  * @param uj An initialized uJSON context.
366  * @return OK or error.
367  */
368 status_t handle_ibex_fi_char_register_file_read(ujson_t *uj);
369 
370 /**
371  * ibex.fi.char.reg_op_loop command handler.
372  *
373  * This FI penetration tests executes the following instructions:
374  * - Initialize register x5=0 & x6=10000
375  * - Add 100 NOPs to delay the trigger
376  * - Perform 10000 x5 = x5 + 1 additions and x6 = x6 - 1 subtractions
377  * - Return the values over UART.
378  *
379  * Faults are injected during the trigger_high & trigger_low.
380  * It needs to be ensured that the compiler does not optimize this code.
381  *
382  * @param uj An initialized uJSON context.
383  * @return OK or error.
384  */
385 status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj);
386 
387 /**
388  * ibex.fi.char.sram_read command handler.
389  *
390  * This FI penetration tests executes the following instructions:
391  * - Write reference values into SRAM.
392  * - Set the trigger.
393  * - Add 10 NOPs to delay the trigger
394  * - Read values from SRAM.
395  * - Unset the trigger.
396  * - Compare the values.
397  * - Return the values over UART.
398  *
399  * Faults are injected during the trigger_high & trigger_low.
400  * It needs to be ensured that the compiler does not optimize this code.
401  *
402  * @param uj An initialized uJSON context.
403  * @return OK or error.
404  */
405 status_t handle_ibex_fi_char_sram_read(ujson_t *uj);
406 
407 /**
408  * ibex.fi.char.sram_static command handler.
409  *
410  * This FI penetration tests executes the following instructions:
411  * - Write ref_values[0] to the 4kB retention SRAM.
412  * - Set the trigger.
413  * - Add 1000 NOPs to give the setup the chance to inject faults.
414  * - Unset the trigger.
415  * - Read back content of the ret. SRAM and compare against reference value.
416  * - If faulty words are detected, transmit addresses back to host.
417  *
418  * Faults are injected during the trigger_high & trigger_low.
419  * It needs to be ensured that the compiler does not optimize this code.
420  *
421  * @param uj An initialized uJSON context.
422  * @return OK or error.
423  */
424 status_t handle_ibex_fi_char_sram_static(ujson_t *uj);
425 
426 /**
427  * ibex.fi.char.sram_write command handler.
428  *
429  * This FI penetration tests executes the following instructions:
430  * - Set the trigger.
431  * - Add 10 NOPs to delay the trigger
432  * - Write 32 values into SRAM.
433  * - Unset the trigger.
434  * - Read back values and compare.
435  * - Return the values over UART.
436  *
437  * Faults are injected during the trigger_high & trigger_low.
438  * It needs to be ensured that the compiler does not optimize this code.
439  *
440  * @param uj An initialized uJSON context.
441  * @return OK or error.
442  */
443 status_t handle_ibex_fi_char_sram_write(ujson_t *uj);
444 
445 /**
446  * ibex.fi.char.sram_write_read command handler.
447  *
448  * This FI penetration tests executes the following instructions:
449  * - Set the trigger.
450  * - Add 10 NOPs to delay the trigger
451  * - Do 16 times:
452  * - sw t0, 0(SRAM_ADDR)
453  * - lw t0, 0(SRAM_ADDR)
454  * - sw t1, 0(SRAM_ADDR)
455  * - lw t1, 0(SRAM_ADDR)
456  * - sw t2, 0(SRAM_ADDR)
457  * - lw t2, 0(SRAM_ADDR)
458  * - Unset the trigger.
459  * - Read back values and compare.
460  * - Return the values over UART.
461  *
462  * Faults are injected during the trigger_high & trigger_low.
463  * It needs to be ensured that the compiler does not optimize this code.
464  *
465  * @param uj An initialized uJSON context.
466  * @return OK or error.
467  */
468 status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj);
469 
470 /**
471  * ibex.fi.char.sram_write_static_unrolled command handler.
472  *
473  * This FI penetration tests executes the following instructions:
474  * - Set the trigger.
475  * - Add 10 NOPs to delay the trigger
476  * - Write 32 static values into SRAM.
477  * - Unset the trigger.
478  * - Read back values and compare.
479  * - Return the values over UART.
480  *
481  * Faults are injected during the trigger_high & trigger_low.
482  * It needs to be ensured that the compiler does not optimize this code.
483  *
484  * @param uj An initialized uJSON context.
485  * @return OK or error.
486  */
487 status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj);
488 
489 /**
490  * ibex.fi.char.unconditional_branch command handler.
491  *
492  * This FI penetration tests executes the following instructions:
493  * - Add 10 NOPs to delay the trigger
494  * - Execute 30 JAL uncond. branches to the following instruction sequence:
495  * addi x5, x5, 1
496  * ret
497  * - Return the increment counter value over UART.
498  * Faults are injected during the trigger_high & trigger_low.
499  * It needs to be ensured that the compiler does not optimize this code.
500  *
501  * @param uj An initialized uJSON context.
502  * @return OK or error.
503  */
504 status_t handle_ibex_fi_char_unconditional_branch(ujson_t *uj);
505 
506 /**
507  * ibex.fi.char.unconditional_branch_nop command handler.
508  *
509  * This FI penetration tests executes the following instructions:
510  * - Add 10 NOPs to delay the trigger
511  * - Execute 30 JAL uncond. branches to the following instruction sequence:
512  * ret
513  * 10x addi x5, x5, 1
514  * ret
515  * - Return the increment counter value over UART.
516  * Faults are injected during the trigger_high & trigger_low.
517  * It needs to be ensured that the compiler does not optimize this code.
518  *
519  * @param uj An initialized uJSON context.
520  * @return OK or error.
521  */
522 status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj);
523 
524 /**
525  * ibex.fi.char.unrolled_mem_op_loop command handler.
526  *
527  * This FI penetration tests executes the following instructions:
528  * - Add 100 NOPs to delay the trigger
529  * - 10000 iterations:
530  * - Load loop_counter value into x5: lw x5, (&loop_counter)
531  * - Increment loop counter: addi x5, x5, 1
532  * - Store loop counter back to loop_counter: sw x5, (&loop_counter)
533  * - Return the value over UART.
534  * Faults are injected during the trigger_high & trigger_low.
535  * It needs to be ensured that the compiler does not optimize this code.
536  *
537  * @param uj An initialized uJSON context.
538  * @return OK or error.
539  */
540 status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj);
541 
542 /**
543  * ibex.fi.char.unrolled_reg_op_loop command handler.
544  *
545  * This FI penetration tests executes the following instructions:
546  * - Initialize register x5=0
547  * - Add 100 NOPs to delay the trigger
548  * - Perform 10000 x5 = x5 + 1 additions
549  * - Return the value over UART.
550  *
551  * Faults are injected during the trigger_high & trigger_low.
552  * It needs to be ensured that the compiler does not optimize this code.
553  *
554  * @param uj An initialized uJSON context.
555  * @return OK or error.
556  */
557 status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj);
558 
559 /**
560  * ibex.fi.char.unrolled_reg_op_loop_chain command handler.
561  *
562  * This FI penetration tests executes the following instructions:
563  * - Initialize register x5=0; x6=0; x7=0; x28=0; x29=0; x30=0
564  * - Add 10 NOPs to delay the trigger
565  * - Perform 10 `chained` additions defined as following:
566  * - x6 = x5 + 1
567  * - x7 = x6 + 1
568  * - x28 = x7 + 1
569  * - x29 = x28 + 1
570  * - x30 = x29 + 1
571  * - x5 = x30 + 1
572  * - Return the 6 register values over UART.
573  *
574  * Faults are injected during the trigger_high & trigger_low.
575  * It needs to be ensured that the compiler does not optimize this code.
576  *
577  * @param uj An initialized uJSON context.
578  * @return OK or error.
579  */
580 status_t handle_ibex_fi_char_unrolled_reg_op_loop_chain(ujson_t *uj);
581 
582 /**
583  * Initializes the trigger and configures the device for the Ibex FI test.
584  *
585  * @param uj An initialized uJSON context.
586  * @return OK or error.
587  */
588 status_t handle_ibex_fi_init(ujson_t *uj);
589 
590 /**
591  * otp_ctrl.data_read command handler.
592  *
593  * This FI penetration tests executes the following instructions:
594  * - Add 10 NOPs to delay the trigger.
595  * - Read VENDOR_TEST, CREATOR_SW_CFG, and OWNER_SW_CFG partition from OTP
596  * - Compare against reference values
597  *
598  * Faults are injected during the trigger_high & trigger_low.
599  *
600  * @param uj An initialized uJSON context.
601  * @return OK or error.
602  */
603 status_t handle_ibex_fi_otp_data_read(ujson_t *uj);
604 
605 /**
606  * otp_ctrl.read_lock command handler.
607  *
608  * This FI penetration tests executes the following instructions:
609  * - Lock the read for VENDOR_TEST, CREATOR_SW_CFG, and OWNER_SW_CFG partition
610  * - Add 10 NOPs to delay the trigger.
611  * - Read VENDOR_TEST, CREATOR_SW_CFG, and OWNER_SW_CFG partition from OTP
612  * - Compare against reference values
613  *
614  * Faults are injected during the trigger_high & trigger_low.
615  *
616  * @param uj An initialized uJSON context.
617  * @return OK or error.
618  */
619 status_t handle_ibex_fi_otp_read_lock(ujson_t *uj);
620 
621 /**
622  * otp_ctrl.write_lock command handler.
623  *
624  * This FI penetration tests executes the following instructions:
625  * - Add 10 NOPs to delay the trigger.
626  * - Try writing to the locked Unlock Token field in the Secret0 partition.
627  *
628  * Faults are injected during the trigger_high & trigger_low.
629  *
630  * @param uj An initialized uJSON context.
631  * @return OK or error.
632  */
633 status_t handle_ibex_fi_otp_write_lock(ujson_t *uj);
634 
635 /**
636  * Ibex FI command handler.
637  *
638  * Command handler for the Ibex FI command.
639  *
640  * @param uj An initialized uJSON context.
641  * @return OK or error.
642  */
643 status_t handle_ibex_fi(ujson_t *uj);
644 
645 #endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_FI_IBEX_FI_H_