utils.h
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. */ 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__ */