/** * \file common.h * \brief Utility functions for use in liboqs. * * SPDX-License-Identifier: MIT */ #ifndef OQS_COMMON_H #define OQS_COMMON_H #include #include #include #include #include #if defined(__cplusplus) extern "C" { #endif /** * Macro for terminating the program if x is * a null pointer. */ #define OQS_EXIT_IF_NULLPTR(x, loc) \ do { \ if ( (x) == (void*)0 ) { \ fprintf(stderr, "Unexpected NULL returned from %s API. Exiting.\n", loc); \ exit(EXIT_FAILURE); \ } \ } while (0) /** * This macro is intended to replace those assert()s * involving side-effecting statements in aes/aes_ossl.c. * * assert() becomes a no-op when -DNDEBUG is defined, * which causes compilation failures when the statement * being checked also results in side-effects. * * This is a temporary workaround until a better error * handling strategy is developed. */ #define OQS_OPENSSL_GUARD(x) \ do { \ if( 1 != (x) ) { \ fprintf(stderr, "Error return value from OpenSSL API: %d. Exiting.\n", x); \ exit(EXIT_FAILURE); \ } \ } while (0) /** * Certain functions (such as OQS_randombytes_openssl in * src/rand/rand.c) take in a size_t parameter, but can * only handle values up to INT_MAX for those parameters. * This macro is a temporary workaround for such functions. */ #define SIZE_T_TO_INT_OR_EXIT(size_t_var_name, int_var_name) \ int int_var_name = 0; \ if (size_t_var_name <= INT_MAX) { \ int_var_name = (int)size_t_var_name; \ } else { \ exit(EXIT_FAILURE); \ } /** * Defines which functions should be exposed outside the LibOQS library * * By default the visibility of all the symbols is defined to "hidden" * Only the library API should be marked as default * * Example: OQS_API return_value function_name(void); */ #if defined(_WIN32) #define OQS_API __declspec(dllexport) #else #define OQS_API __attribute__((visibility("default"))) #endif #if defined(OQS_SYS_UEFI) #undef OQS_API #define OQS_API #endif /** * Represents return values from functions. * * Callers should compare with the symbol rather than the individual value. * For example, * * ret = OQS_KEM_encaps(...); * if (ret == OQS_SUCCESS) { ... } * * rather than * * if (!OQS_KEM_encaps(...) { ... } * */ typedef enum { /** Used to indicate that some undefined error occurred. */ OQS_ERROR = -1, /** Used to indicate successful return from function. */ OQS_SUCCESS = 0, /** Used to indicate failures in external libraries (e.g., OpenSSL). */ OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50, } OQS_STATUS; /** * CPU runtime detection flags */ typedef enum { OQS_CPU_EXT_INIT, /* Must be first */ /* Start extension list */ OQS_CPU_EXT_ADX, OQS_CPU_EXT_AES, OQS_CPU_EXT_AVX, OQS_CPU_EXT_AVX2, OQS_CPU_EXT_AVX512, OQS_CPU_EXT_BMI1, OQS_CPU_EXT_BMI2, OQS_CPU_EXT_PCLMULQDQ, OQS_CPU_EXT_VPCLMULQDQ, OQS_CPU_EXT_POPCNT, OQS_CPU_EXT_SSE, OQS_CPU_EXT_SSE2, OQS_CPU_EXT_SSE3, OQS_CPU_EXT_ARM_AES, OQS_CPU_EXT_ARM_SHA2, OQS_CPU_EXT_ARM_SHA3, OQS_CPU_EXT_ARM_NEON, /* End extension list */ OQS_CPU_EXT_COUNT, /* Must be last */ } OQS_CPU_EXT; /** * Checks if the CPU supports a given extension * * \return 1 if the given CPU extension is available, 0 otherwise. */ OQS_API int OQS_CPU_has_extension(OQS_CPU_EXT ext); /** * This currently sets the values in the OQS_CPU_EXTENSIONS * and prefetches the OpenSSL objects if necessary. */ OQS_API void OQS_init(void); /** * This function frees prefetched OpenSSL objects */ OQS_API void OQS_destroy(void); /** * Return library version string. */ OQS_API const char *OQS_version(void); /** * Constant time comparison of byte sequences `a` and `b` of length `len`. * Returns 0 if the byte sequences are equal or if `len`=0. * Returns 1 otherwise. * * @param[in] a A byte sequence of length at least `len`. * @param[in] b A byte sequence of length at least `len`. * @param[in] len The number of bytes to compare. */ OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len); /** * Zeros out `len` bytes of memory starting at `ptr`. * * Designed to be protected against optimizing compilers which try to remove * "unnecessary" operations. Should be used for all buffers containing secret * data. * * @param[in] ptr The start of the memory to zero out. * @param[in] len The number of bytes to zero out. */ OQS_API void OQS_MEM_cleanse(void *ptr, size_t len); /** * Zeros out `len` bytes of memory starting at `ptr`, then frees `ptr`. * * Can be called with `ptr = NULL`, in which case no operation is performed. * * Designed to be protected against optimizing compilers which try to remove * "unnecessary" operations. Should be used for all buffers containing secret * data. * * @param[in] ptr The start of the memory to zero out and free. * @param[in] len The number of bytes to zero out. */ OQS_API void OQS_MEM_secure_free(void *ptr, size_t len); /** * Frees `ptr`. * * Can be called with `ptr = NULL`, in which case no operation is performed. * * Should only be used on non-secret data. * * @param[in] ptr The start of the memory to free. */ OQS_API void OQS_MEM_insecure_free(void *ptr); /** * Internal implementation of C11 aligned_alloc to work around compiler quirks. * * Allocates size bytes of uninitialized memory with a base pointer that is * a multiple of alignment. Alignment must be a power of two and a multiple * of sizeof(void *). Size must be a multiple of alignment. */ void *OQS_MEM_aligned_alloc(size_t alignment, size_t size); /** * Free memory allocated with OQS_MEM_aligned_alloc. */ void OQS_MEM_aligned_free(void *ptr); #if defined(__cplusplus) } // extern "C" #endif #endif // OQS_COMMON_H