/* * Copyright (C) 2017 - This file is part of libecc project * * Authors: * Ryad BENADJILA <ryadbenadjila@gmail.com> * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> * * Contributors: * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> * * This software is licensed under a dual BSD and GPL v2 license. * See LICENSE file at the root folder of the project. */ #ifndef __UTILS_H__ #define __UTILS_H__ #include <libecc/words/words.h> /* * At various locations in the code, we expect expect some specific * conditions to be true for correct operation of the code after * those locations. This is commonly the case on input parameters * at the beginning of functions. Other conditions may be expected * but are not necessarily impacting for correct operation of the * code. * * We use the three following macros for that purpose: * * MUST_HAVE(): The condition is always tested, i.e. both in debug * and non debug build. This macros is used when it's better not to * continue if the condition does not hold. In production code, * if the condition does not hold, a while (1) loop is currently * executed (but this may be changed for some specific code the * system provide (e.g. abort())). In debug mode, an assert() is * used when the condition is false. * * SHOULD_HAVE(): the condition is only executed in debug mode and * the whole macros is a nop in production code. This can be used * to add more checks in the code to detect specific conditions * or changes. Those checks may have performance impact which are * acceptable in debug mode but are not in production mode. * * KNOWN_FACT(): the condition is only executed in debug mode and * the whole macro is a nop in production code. This macro is used * to add conditions that are known to be true which may help analysis * tools to work on the code. The macro can be used in order to make * those conditions explicit. */ /* Some helper for printing where we have an issue */ #if defined(USE_ASSERT_PRINT) #include <libecc/external_deps/print.h> #define MUST_HAVE_EXT_PRINT do { \ ext_printf("MUST_HAVE error: %s at %d\n", __FILE__,__LINE__); \ } while (0) #define SHOULD_HAVE_EXT_PRINT do { \ ext_printf("SHOULD_HAVE error: %s at %d\n", __FILE__,__LINE__); \ } while (0) #define KNOWN_FACT_EXT_PRINT do { \ ext_printf("KNOWN_FACT error: %s at %d\n", __FILE__,__LINE__); \ } while (0) #else #define MUST_HAVE_EXT_PRINT #define SHOULD_HAVE_EXT_PRINT #define KNOWN_FACT_EXT_PRINT #endif /* * We known it is BAD BAD BAD to define macro with goto inside them * but this is the best way we found to avoid making the code * unreadable with tests of error conditions when implementing * error handling in the project. * * EG stands for Error Goto, which represents the purpose of the * macro, i.e. test a condition cond, and if false goto label * lbl. */ #define EG(cond,lbl) do { if (cond) { goto lbl ; } } while (0) /****** Regular DEBUG and production modes cases ****************/ /****** DEBUG mode ***********************************************/ #if defined(DEBUG) #include <assert.h> /* * In DEBUG mode, we enforce a regular assert() in MUST_HAVE, * SHOULD_HAVE and KNOWN_FACT, i.e. they are all the same. */ #define MUST_HAVE(cond, ret, lbl) do { \ if(!(cond)){ \ MUST_HAVE_EXT_PRINT; \ } \ assert((cond)); \ if (0) { /* silence unused \ label warning */ \ ret = -1; \ goto lbl; \ } \ } while (0) #define SHOULD_HAVE(cond, ret, lbl) do {\ if(!(cond)){ \ SHOULD_HAVE_EXT_PRINT; \ } \ assert((cond)); \ if (0) { /* silence unused \ label warning */ \ ret = -1; \ goto lbl; \ } \ } while (0) #define KNOWN_FACT(cond, ret, lbl) do { \ if(!(cond)){ \ KNOWN_FACT_EXT_PRINT; \ } \ assert((cond)); \ if (0) { /* silence unused \ label warning */ \ ret = -1; \ goto lbl; \ } \ } while (0) /****** Production mode ******************************************/ #else /* !defined(DEBUG) */ /* * In regular production mode, SHOULD_HAVE and KNOWN_FACT are void for * performance reasons. MUST_HAVE includes an ext_printf call for * tracing the origin of the error when necessary (if USE_ASSERT_PRINT * is specified by the user). */ #define MUST_HAVE(cond, ret, lbl) do { \ if (!(cond)) { \ MUST_HAVE_EXT_PRINT; \ ret = -1; \ goto lbl; \ } \ } while (0) #define SHOULD_HAVE(cond, ret, lbl) do { \ if (0) { /* silence unused \ label warning */ \ ret = -1; \ goto lbl; \ } \ } while (0) #define KNOWN_FACT(cond, ret, lbl) do { \ if (0) { /* silence unused \ label warning */ \ ret = -1; \ goto lbl; \ } \ } while (0) /******************************************************************/ #endif /* defined(DEBUG) */ #define LOCAL_MAX(x, y) (((x) > (y)) ? (x) : (y)) #define LOCAL_MIN(x, y) (((x) < (y)) ? (x) : (y)) #define BYTECEIL(numbits) (((numbits) + 7) / 8) ATTRIBUTE_WARN_UNUSED_RET int are_equal(const void *a, const void *b, u32 len, int *check); ATTRIBUTE_WARN_UNUSED_RET int local_memcpy(void *dst, const void *src, u32 n); ATTRIBUTE_WARN_UNUSED_RET int local_memset(void *v, u8 c, u32 n); ATTRIBUTE_WARN_UNUSED_RET int are_str_equal(const char *s1, const char *s2, int *check); ATTRIBUTE_WARN_UNUSED_RET int are_str_equal_nlen(const char *s1, const char *s2, u32 maxlen, int *check); ATTRIBUTE_WARN_UNUSED_RET int local_strlen(const char *s, u32 *len); ATTRIBUTE_WARN_UNUSED_RET int local_strnlen(const char *s, u32 maxlen, u32 *len); ATTRIBUTE_WARN_UNUSED_RET int local_strncpy(char *dst, const char *src, u32 n); ATTRIBUTE_WARN_UNUSED_RET int local_strncat(char *dest, const char *src, u32 n); /* Return 1 if architecture is big endian, 0 otherwise. */ static inline int arch_is_big_endian(void) { const u16 val = 0x0102; const u8 *buf = (const u8 *)(&val); return buf[0] == 0x01; } #define VAR_ZEROIFY(x) do { \ x = 0; \ } while (0) #define PTR_NULLIFY(x) do { \ x = NULL; \ } while (0) #endif /* __UTILS_H__ */