1 /*
2  * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "fih.h"
9 #include "tfm_hal_defs.h"
10 #include "tfm_hal_platform.h"
11 #ifdef FIH_ENABLE_DELAY
12 #include "tfm_fih_rng.h"
13 #endif
14 
15 #ifdef TFM_FIH_PROFILE_ON
16 fih_int FIH_SUCCESS = FIH_INT_INIT(FIH_POSITIVE_VALUE);
17 fih_int FIH_FAILURE = FIH_INT_INIT(FIH_NEGATIVE_VALUE);
18 #endif
19 
20 #ifdef FIH_ENABLE_CFI
21 fih_int _fih_cfi_ctr = FIH_INT_INIT(0);
22 
fih_cfi_get_and_increment(uint8_t cnt)23 fih_int fih_cfi_get_and_increment(uint8_t cnt)
24 {
25     fih_int saved_ctr = _fih_cfi_ctr;
26 
27     if (fih_int_decode(_fih_cfi_ctr) < 0) {
28         FIH_PANIC;
29     }
30 
31     /* Overflow */
32     if (fih_int_decode(_fih_cfi_ctr) > (fih_int_decode(_fih_cfi_ctr) + cnt)) {
33         FIH_PANIC;
34     }
35 
36     _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) + cnt);
37 
38     fih_int_validate(_fih_cfi_ctr);
39     fih_int_validate(saved_ctr);
40 
41     return saved_ctr;
42 }
43 
fih_cfi_validate(fih_int saved)44 void fih_cfi_validate(fih_int saved)
45 {
46     volatile int32_t rc = FIH_FALSE;
47 
48     rc = fih_eq(saved, _fih_cfi_ctr);
49     if (rc != FIH_TRUE) {
50         FIH_PANIC;
51     }
52 }
53 
fih_cfi_decrement(void)54 void fih_cfi_decrement(void)
55 {
56     if (fih_int_decode(_fih_cfi_ctr) < 1) {
57         FIH_PANIC;
58     }
59 
60     _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) - 1);
61 
62     fih_int_validate(_fih_cfi_ctr);
63 }
64 #endif /* FIH_ENABLE_CFI */
65 
66 #ifdef FIH_ENABLE_GLOBAL_FAIL
67 /* Global failure loop for bootloader code. Uses attribute used to prevent
68  * compiler removing due to non-standard calling procedure. Multiple loop jumps
69  * used to make unlooping difficult.
70  */
71 __attribute__((used))
72 __attribute__((noinline))
fih_panic_loop(void)73 void fih_panic_loop(void)
74 {
75     FIH_LABEL("FAILURE_LOOP");
76     __asm volatile ("b fih_panic_loop");
77     __asm volatile ("b fih_panic_loop");
78     __asm volatile ("b fih_panic_loop");
79     __asm volatile ("b fih_panic_loop");
80     __asm volatile ("b fih_panic_loop");
81     __asm volatile ("b fih_panic_loop");
82     __asm volatile ("b fih_panic_loop");
83     __asm volatile ("b fih_panic_loop");
84     __asm volatile ("b fih_panic_loop");
85 }
86 #endif /* FIH_ENABLE_GLOBAL_FAIL */
87 
88 #ifdef FIH_ENABLE_DELAY
fih_delay_init(void)89 void fih_delay_init(void)
90 {
91     fih_int ret = FIH_FAILURE;
92 
93     ret = tfm_fih_random_init();
94 
95 #ifdef FIH_ENABLE_DOUBLE_VARS
96     if (ret.val != FIH_SUCCESS.val) {
97         FIH_PANIC;
98     }
99 
100     if (ret.msk != FIH_SUCCESS.msk) {
101         FIH_PANIC;
102     }
103 #else /* FIH_ENABLE_DOUBLE_VARS */
104     if (ret != FIH_SUCCESS) {
105         FIH_PANIC;
106     }
107 #endif /* FIH_ENABLE_DOUBLE_VARS */
108 }
109 
fih_delay_random(void)110 uint8_t fih_delay_random(void)
111 {
112     uint8_t rand_value = 0xFF;
113 
114     /* Repeat random generation to mitigate instruction skip */
115     tfm_fih_random_generate(&rand_value);
116     tfm_fih_random_generate(&rand_value);
117     tfm_fih_random_generate(&rand_value);
118 
119     return rand_value;
120 }
121 #endif /* FIH_ENABLE_DELAY */
122