1 /*
2 * Copyright (C) 2017 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8 *
9 * Contributors:
10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12 *
13 * This software is licensed under a dual BSD and GPL v2 license.
14 * See LICENSE file at the root folder of the project.
15 */
16 #ifndef __UTILS_H__
17 #define __UTILS_H__
18
19 #include <libecc/words/words.h>
20
21 /*
22 * At various locations in the code, we expect expect some specific
23 * conditions to be true for correct operation of the code after
24 * those locations. This is commonly the case on input parameters
25 * at the beginning of functions. Other conditions may be expected
26 * but are not necessarily impacting for correct operation of the
27 * code.
28 *
29 * We use the three following macros for that purpose:
30 *
31 * MUST_HAVE(): The condition is always tested, i.e. both in debug
32 * and non debug build. This macros is used when it's better not to
33 * continue if the condition does not hold. In production code,
34 * if the condition does not hold, a while (1) loop is currently
35 * executed (but this may be changed for some specific code the
36 * system provide (e.g. abort())). In debug mode, an assert() is
37 * used when the condition is false.
38 *
39 * SHOULD_HAVE(): the condition is only executed in debug mode and
40 * the whole macros is a nop in production code. This can be used
41 * to add more checks in the code to detect specific conditions
42 * or changes. Those checks may have performance impact which are
43 * acceptable in debug mode but are not in production mode.
44 *
45 * KNOWN_FACT(): the condition is only executed in debug mode and
46 * the whole macro is a nop in production code. This macro is used
47 * to add conditions that are known to be true which may help analysis
48 * tools to work on the code. The macro can be used in order to make
49 * those conditions explicit.
50 */
51
52 /* Some helper for printing where we have an issue */
53 #if defined(USE_ASSERT_PRINT)
54 #include <libecc/external_deps/print.h>
55 #define MUST_HAVE_EXT_PRINT do { \
56 ext_printf("MUST_HAVE error: %s at %d\n", __FILE__,__LINE__); \
57 } while (0)
58 #define SHOULD_HAVE_EXT_PRINT do { \
59 ext_printf("SHOULD_HAVE error: %s at %d\n", __FILE__,__LINE__); \
60 } while (0)
61 #define KNOWN_FACT_EXT_PRINT do { \
62 ext_printf("KNOWN_FACT error: %s at %d\n", __FILE__,__LINE__); \
63 } while (0)
64 #else
65 #define MUST_HAVE_EXT_PRINT
66 #define SHOULD_HAVE_EXT_PRINT
67 #define KNOWN_FACT_EXT_PRINT
68 #endif
69
70 /*
71 * We known it is BAD BAD BAD to define macro with goto inside them
72 * but this is the best way we found to avoid making the code
73 * unreadable with tests of error conditions when implementing
74 * error handling in the project.
75 *
76 * EG stands for Error Goto, which represents the purpose of the
77 * macro, i.e. test a condition cond, and if false goto label
78 * lbl.
79 */
80 #define EG(cond,lbl) do { if (cond) { goto lbl ; } } while (0)
81
82 /****** Regular DEBUG and production modes cases ****************/
83
84 /****** DEBUG mode ***********************************************/
85 #if defined(DEBUG)
86 #include <assert.h>
87 /*
88 * In DEBUG mode, we enforce a regular assert() in MUST_HAVE,
89 * SHOULD_HAVE and KNOWN_FACT, i.e. they are all the same.
90 */
91
92 #define MUST_HAVE(cond, ret, lbl) do { \
93 if(!(cond)){ \
94 MUST_HAVE_EXT_PRINT; \
95 } \
96 assert((cond)); \
97 if (0) { /* silence unused \
98 label warning */ \
99 ret = -1; \
100 goto lbl; \
101 } \
102 } while (0)
103
104 #define SHOULD_HAVE(cond, ret, lbl) do {\
105 if(!(cond)){ \
106 SHOULD_HAVE_EXT_PRINT; \
107 } \
108 assert((cond)); \
109 if (0) { /* silence unused \
110 label warning */ \
111 ret = -1; \
112 goto lbl; \
113 } \
114 } while (0)
115
116 #define KNOWN_FACT(cond, ret, lbl) do { \
117 if(!(cond)){ \
118 KNOWN_FACT_EXT_PRINT; \
119 } \
120 assert((cond)); \
121 if (0) { /* silence unused \
122 label warning */ \
123 ret = -1; \
124 goto lbl; \
125 } \
126 } while (0)
127
128 /****** Production mode ******************************************/
129 #else /* !defined(DEBUG) */
130
131 /*
132 * In regular production mode, SHOULD_HAVE and KNOWN_FACT are void for
133 * performance reasons. MUST_HAVE includes an ext_printf call for
134 * tracing the origin of the error when necessary (if USE_ASSERT_PRINT
135 * is specified by the user).
136 */
137 #define MUST_HAVE(cond, ret, lbl) do { \
138 if (!(cond)) { \
139 MUST_HAVE_EXT_PRINT; \
140 ret = -1; \
141 goto lbl; \
142 } \
143 } while (0)
144
145 #define SHOULD_HAVE(cond, ret, lbl) do { \
146 if (0) { /* silence unused \
147 label warning */ \
148 ret = -1; \
149 goto lbl; \
150 } \
151 } while (0)
152
153 #define KNOWN_FACT(cond, ret, lbl) do { \
154 if (0) { /* silence unused \
155 label warning */ \
156 ret = -1; \
157 goto lbl; \
158 } \
159 } while (0)
160
161 /******************************************************************/
162 #endif /* defined(DEBUG) */
163
164 #define LOCAL_MAX(x, y) (((x) > (y)) ? (x) : (y))
165 #define LOCAL_MIN(x, y) (((x) < (y)) ? (x) : (y))
166
167 #define BYTECEIL(numbits) (((numbits) + 7) / 8)
168
169 ATTRIBUTE_WARN_UNUSED_RET int are_equal(const void *a, const void *b, u32 len, int *check);
170 ATTRIBUTE_WARN_UNUSED_RET int local_memcpy(void *dst, const void *src, u32 n);
171 ATTRIBUTE_WARN_UNUSED_RET int local_memset(void *v, u8 c, u32 n);
172 ATTRIBUTE_WARN_UNUSED_RET int are_str_equal(const char *s1, const char *s2, int *check);
173 ATTRIBUTE_WARN_UNUSED_RET int are_str_equal_nlen(const char *s1, const char *s2, u32 maxlen, int *check);
174 ATTRIBUTE_WARN_UNUSED_RET int local_strlen(const char *s, u32 *len);
175 ATTRIBUTE_WARN_UNUSED_RET int local_strnlen(const char *s, u32 maxlen, u32 *len);
176 ATTRIBUTE_WARN_UNUSED_RET int local_strncpy(char *dst, const char *src, u32 n);
177 ATTRIBUTE_WARN_UNUSED_RET int local_strncat(char *dest, const char *src, u32 n);
178
179 /* Return 1 if architecture is big endian, 0 otherwise. */
arch_is_big_endian(void)180 static inline int arch_is_big_endian(void)
181 {
182 const u16 val = 0x0102;
183 const u8 *buf = (const u8 *)(&val);
184
185 return buf[0] == 0x01;
186 }
187
188 #define VAR_ZEROIFY(x) do { \
189 x = 0; \
190 } while (0)
191
192 #define PTR_NULLIFY(x) do { \
193 x = NULL; \
194 } while (0)
195
196 #endif /* __UTILS_H__ */
197