1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2022, Linaro Limited
4 */
5
6 #include <compiler.h>
7 #include <fault_mitigation.h>
8
9 #ifndef __KERNEL__
10 struct ftmn_func_arg *__ftmn_global_func_arg;
11 #endif
12
13 /*
14 * These functions can be implemented in assembly if needed. They would
15 * provide the same API but an implementation more resilient to fault
16 * injections.
17 *
18 * For now there is no need since it's enough with the single redundancy
19 * provided just by having these function implemented separately from where
20 * they are used.
21 */
22
___ftmn_return_res(struct ftmn_check * check,unsigned long steps,unsigned long res)23 unsigned long __weak ___ftmn_return_res(struct ftmn_check *check,
24 unsigned long steps, unsigned long res)
25 {
26 if (check->steps != steps)
27 FTMN_PANIC();
28 if ((check->res ^ FTMN_DEFAULT_HASH) != res)
29 FTMN_PANIC();
30 return res;
31 }
32
___ftmn_expect_state(struct ftmn_check * check,enum ftmn_incr incr,unsigned long steps,unsigned long res)33 void __weak ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr,
34 unsigned long steps, unsigned long res)
35 {
36 if ((check->res ^ FTMN_DEFAULT_HASH) != res)
37 FTMN_PANIC();
38 if (check->steps != steps)
39 FTMN_PANIC();
40 check->steps += incr;
41 }
42
___ftmn_callee_done(struct ftmn_func_arg * arg,unsigned long my_hash,unsigned long res)43 void __weak ___ftmn_callee_done(struct ftmn_func_arg *arg,
44 unsigned long my_hash,
45 unsigned long res)
46 {
47 arg->hash ^= my_hash;
48 arg->res = arg->hash ^ res;
49 }
50
___ftmn_callee_done_not_zero(struct ftmn_func_arg * arg,unsigned long my_hash,unsigned long res)51 void __weak ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg,
52 unsigned long my_hash,
53 unsigned long res)
54 {
55 if (res == 0)
56 FTMN_PANIC();
57 arg->hash ^= my_hash;
58 arg->res = arg->hash ^ res;
59 }
60
___ftmn_callee_done_memcmp(struct ftmn_func_arg * arg,unsigned long my_hash,int res,ftmn_memcmp_t my_memcmp,const void * p1,const void * p2,size_t nb)61 void __weak ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg,
62 unsigned long my_hash, int res,
63 ftmn_memcmp_t my_memcmp,
64 const void *p1, const void *p2,
65 size_t nb)
66 {
67 int res2 = 0;
68
69 if (!nb)
70 FTMN_PANIC();
71
72 res2 = my_memcmp(p1, p2, nb);
73 if (res2 != res)
74 FTMN_PANIC();
75
76 arg->hash ^= my_hash;
77 arg->res = arg->hash ^ res;
78 }
79
___ftmn_callee_done_check(struct ftmn_func_arg * arg,unsigned long my_hash,struct ftmn_check * check,enum ftmn_incr incr,unsigned long steps,unsigned long res)80 void __weak ___ftmn_callee_done_check(struct ftmn_func_arg *arg,
81 unsigned long my_hash,
82 struct ftmn_check *check,
83 enum ftmn_incr incr, unsigned long steps,
84 unsigned long res)
85 {
86 if ((check->res ^ FTMN_DEFAULT_HASH) != res)
87 FTMN_PANIC();
88 if (check->steps != steps)
89 FTMN_PANIC();
90
91 check->steps += incr;
92 if (arg) {
93 arg->hash ^= my_hash;
94 arg->res = check->res ^ FTMN_DEFAULT_HASH ^ arg->hash;
95 }
96
97 }
98
___ftmn_callee_update_not_zero(struct ftmn_func_arg * arg,unsigned long res)99 void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg,
100 unsigned long res)
101 {
102 if (!res)
103 FTMN_PANIC();
104 arg->res = arg->hash ^ res;
105 }
106
107
___ftmn_copy_linked_call_res(struct ftmn_check * check,enum ftmn_incr incr,struct ftmn_func_arg * arg,unsigned long res)108 void __weak ___ftmn_copy_linked_call_res(struct ftmn_check *check,
109 enum ftmn_incr incr,
110 struct ftmn_func_arg *arg,
111 unsigned long res)
112 {
113 if ((arg->res ^ arg->hash) != res)
114 FTMN_PANIC();
115 check->res = res ^ FTMN_DEFAULT_HASH;
116 check->steps += incr;
117 }
118
___ftmn_set_check_res(struct ftmn_check * check,enum ftmn_incr incr,unsigned long res)119 void __weak ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr,
120 unsigned long res)
121 {
122 check->steps += incr;
123 check->res = res ^ FTMN_DEFAULT_HASH;
124 }
125
___ftmn_set_check_res_not_zero(struct ftmn_check * check,enum ftmn_incr incr,unsigned long res)126 void __weak ___ftmn_set_check_res_not_zero(struct ftmn_check *check,
127 enum ftmn_incr incr,
128 unsigned long res)
129 {
130 if (!res)
131 FTMN_PANIC();
132 check->steps += incr;
133 check->res = res ^ FTMN_DEFAULT_HASH;
134 }
135
___ftmn_set_check_res_memcmp(struct ftmn_check * check,enum ftmn_incr incr,int res,ftmn_memcmp_t my_memcmp,const void * p1,const void * p2,size_t nb)136 void __weak ___ftmn_set_check_res_memcmp(struct ftmn_check *check,
137 enum ftmn_incr incr, int res,
138 ftmn_memcmp_t my_memcmp,
139 const void *p1, const void *p2,
140 size_t nb)
141 {
142 int res2 = 0;
143
144 if (!nb)
145 FTMN_PANIC();
146
147 res2 = my_memcmp(p1, p2, nb);
148 if (res2 != res)
149 FTMN_PANIC();
150
151 check->steps += incr;
152 check->res = FTMN_DEFAULT_HASH ^ res;
153 }
154