1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Copyright (c) 2020 Arm Limited
5  */
6 
7 #include "bootutil/fault_injection_hardening.h"
8 
9 #ifdef FIH_ENABLE_DOUBLE_VARS
10 /* Variable that could be (but isn't) changed at runtime to force the compiler
11  * not to optimize the double check. Value doesn't matter.
12  */
13 volatile int _fih_mask = _FIH_MASK_VALUE;
14 #endif /* FIH_ENABLE_DOUBLE_VARS */
15 
16 fih_ret FIH_SUCCESS = FIH_POSITIVE_VALUE;
17 fih_ret FIH_FAILURE = FIH_NEGATIVE_VALUE;
18 fih_ret FIH_NO_BOOTABLE_IMAGE = FIH_CONST1;
19 fih_ret FIH_BOOT_HOOK_REGULAR = FIH_CONST2;
20 
21 #ifdef FIH_ENABLE_CFI
22 
23 #ifdef FIH_ENABLE_DOUBLE_VARS
24 fih_int _fih_cfi_ctr = {0, 0 ^ _FIH_MASK_VALUE};
25 #else
26 fih_int _fih_cfi_ctr = {0};
27 #endif /* FIH_ENABLE_DOUBLE_VARS */
28 
29 /* Increment the CFI counter by one, and return the value before the increment.
30  */
fih_cfi_get_and_increment(void)31 fih_int fih_cfi_get_and_increment(void)
32 {
33     fih_int saved = _fih_cfi_ctr;
34     _fih_cfi_ctr = fih_int_encode(fih_int_decode(saved) + 1);
35     return saved;
36 }
37 
38 /* Validate that the saved precall value is the same as the value of the global
39  * counter. For this to be the case, a fih_ret must have been called between
40  * these functions being executed. If the values aren't the same then panic.
41  */
fih_cfi_validate(fih_int saved)42 void fih_cfi_validate(fih_int saved)
43 {
44     if (fih_int_decode(saved) != fih_int_decode(_fih_cfi_ctr)) {
45         FIH_PANIC;
46     }
47 }
48 
49 /* Decrement the global CFI counter by one, so that it has the same value as
50  * before the cfi_precall
51  */
fih_cfi_decrement(void)52 void fih_cfi_decrement(void)
53 {
54     _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) - 1);
55 }
56 
57 #endif /* FIH_ENABLE_CFI */
58 
59 #ifdef FIH_ENABLE_GLOBAL_FAIL
60 /* Global failure loop for bootloader code. Uses attribute used to prevent
61  * compiler removing due to non-standard calling procedure. Multiple loop jumps
62  * used to make unlooping difficult.
63  */
64 __attribute__((used))
65 __attribute__((noinline))
fih_panic_loop(void)66 void fih_panic_loop(void)
67 {
68     __asm volatile ("b fih_panic_loop");
69     __asm volatile ("b fih_panic_loop");
70     __asm volatile ("b fih_panic_loop");
71     __asm volatile ("b fih_panic_loop");
72     __asm volatile ("b fih_panic_loop");
73     __asm volatile ("b fih_panic_loop");
74     __asm volatile ("b fih_panic_loop");
75     __asm volatile ("b fih_panic_loop");
76     __asm volatile ("b fih_panic_loop");
77 }
78 #endif /* FIH_ENABLE_GLOBAL_FAIL */
79