xref: /freebsd/crypto/libecc/include/libecc/utils/utils.h (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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