/* port.c * * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #if (defined(__linux__) || defined(__ANDROID__)) && \ !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) && \ !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 #elif defined(__FreeBSD__) /* for __FreeBSD_version */ #include #endif /* wolfCrypt Porting Build Options: Threading/Mutex options: * SINGLE_THREADED: No-op mutex/threading implementations default: off * WOLFSSL_PTHREADS: Use pthread-based mutex/threading default: off * (auto-detected on most POSIX systems) * WOLFSSL_MUTEX_INITIALIZER: Use static mutex initialization default: off * WC_MUTEX_OPS_INLINE: Use inlined mutex operations default: off * WOLFSSL_USER_MUTEX: User-provided mutex implementation default: off * WOLFSSL_COND: Enable condition variable support default: off * WOLFSSL_USE_RWLOCK: Enable reader-writer lock support default: off * WOLFSSL_THREAD_NO_JOIN: Create threads without join default: off * WOLFSSL_ALGO_HW_MUTEX: Per-algorithm hardware mutex locks default: off * Controls AES, hash, PK, and RNG mutexes. * WOLFSSL_CRYPT_HW_MUTEX: Cryptography hardware mutex default: off * Master control for all HW mutex init. * NO_AES_MUTEX: Disable AES hardware mutex default: off * NO_HASH_MUTEX: Disable hash hardware mutex default: off * NO_PK_MUTEX: Disable public-key hardware mutex default: off * NO_RNG_MUTEX: Disable RNG hardware mutex default: off * * Memory options: * USE_WOLFSSL_MEMORY: Enable custom memory allocation hooks default: on * WOLFSSL_STATIC_MEMORY: Use static memory pools instead of default: off * dynamic allocation. * WOLFSSL_TRACK_MEMORY: Enable memory allocation tracking default: off * WOLFSSL_TRACK_MEMORY_VERBOSE: Verbose memory tracking output default: off * WOLFSSL_FORCE_MALLOC_FAIL_TEST: Force malloc failures for default: off * testing error handling paths. * WOLFSSL_MEM_FAIL_COUNT: Count malloc failures for testing default: off * WOLFSSL_CHECK_MEM_ZERO: Verify sensitive memory is zeroed default: off * on free. Debug tool for key material. * * Filesystem options: * NO_FILESYSTEM: Disable all filesystem operations default: off * NO_WOLFSSL_DIR: Disable directory listing/iteration default: off * * Time options: * WOLFSSL_GMTIME: Provide custom gmtime implementation default: off * HAVE_TIME_T_TYPE: Platform provides time_t default: auto * TIME_OVERRIDES: Application provides custom time funcs default: off * USER_TICKS: Application provides tick counter default: off * USE_WOLF_TM: Use wolfSSL struct tm definition default: off * * String function options: * STRING_USER: User provides all string functions default: off * USE_WOLF_STRTOK: Use wolfSSL strtok implementation default: off * USE_WOLF_STRSEP: Use wolfSSL strsep implementation default: off * USE_WOLF_STRLCPY: Use wolfSSL strlcpy implementation default: off * USE_WOLF_STRLCAT: Use wolfSSL strlcat implementation default: off * USE_WOLF_STRCASECMP: Use wolfSSL strcasecmp implementation default: off * USE_WOLF_STRNCASECMP:Use wolfSSL strncasecmp implementation default: off * USE_WOLF_STRDUP: Use wolfSSL strdup implementation default: off * * Atomic operation options: * WOLFSSL_ATOMIC_OPS: Enable atomic operations for thread default: off * safety without full mutexes. * WOLFSSL_USER_DEFINED_ATOMICS: User-provided atomic impl default: off * WOLFSSL_HAVE_ATOMIC_H: Has C11 atomic.h header default: off * * General options: * WOLFCRYPT_ONLY: Exclude TLS/SSL, wolfCrypt only build default: off * WOLFSSL_LEANPSK: Lean PSK build, minimal features default: off * WOLF_C89: C89 compatibility mode default: off * WOLFSSL_SMALL_STACK: Reduce stack usage by allocating from default: off * heap instead. Slower but needed for * constrained environments. * DEBUG_WOLFSSL_VERBOSE: Enable verbose debug logging default: off */ #include #ifdef __APPLE__ #include #endif #include #ifdef HAVE_ENTROPY_MEMUSE #include #endif #ifdef HAVE_ECC #include #endif #ifdef WOLFSSL_ASYNC_CRYPT #include #endif #if defined(HAVE_HASHDRBG) && !defined(WC_NO_RNG) #include #endif #ifdef FREESCALE_LTC_TFM #include #endif #if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD) #include #ifdef WOLF_CRYPTO_CB #include #endif #endif #ifdef WOLFSSL_PSOC6_CRYPTO #include #endif #ifdef MAXQ10XX_MODULE_INIT #include #endif #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \ defined(WOLFSSL_ATECC608A) || \ defined(WOLFSSL_MICROCHIP_TA100) #include #endif #if defined(WOLFSSL_RENESAS_TSIP) #include #endif #if defined(WOLFSSL_RENESAS_FSPSM) #include #endif #if defined(WOLFSSL_RENESAS_RX64_HASH) #include #endif #ifdef WOLFSSL_STSAFE #include #endif #if defined(WOLFSSL_TROPIC01) #include #endif #if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) \ && !defined(WOLFCRYPT_ONLY) #include #endif #include #if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) #include #endif #if defined(WOLFSSL_CAAM) #include #endif #if defined(HAVE_ARIA) #include #endif #if defined(WOLFSSL_DEVCRYPTO) #include #endif #ifdef WOLFSSL_IMXRT_DCP #include #endif #ifdef WOLFSSL_NXP_CASPER #include #endif #ifdef WOLFSSL_NXP_HASHCRYPT #include #endif #ifdef WOLF_CRYPTO_CB #include #endif #ifdef HAVE_INTEL_QA_SYNC #include #endif #ifdef HAVE_CAVIUM_OCTEON_SYNC #include #endif #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT) #include #endif #ifdef WOLFSSL_SCE #include "hal_data.h" #endif #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) #include "rpcmem.h" #endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) #endif #if defined(WOLFSSL_HAVE_PSA) #include #endif #if defined(HAVE_LIBOQS) #include #endif #if defined(FREERTOS) && defined(WOLFSSL_ESPIDF) #include #include /* The Espressif-specific platform include: */ #include #endif #if defined(WOLFSSL_ZEPHYR) #if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM) #include "native_rtc.h" #define CONFIG_RTC #endif #endif /* prevent multiple mutex initializations */ #ifdef WOLFSSL_ATOMIC_OPS wolfSSL_Atomic_Int initRefCount = WOLFSSL_ATOMIC_INITIALIZER(0); #else static int initRefCount = 0; #endif #if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT) int aarch64_use_sb = 0; #endif /* Used to initialize state for wolfcrypt return 0 on success */ WOLFSSL_ABI int wolfCrypt_Init(void) { int ret = 0; int my_initRefCount = wolfSSL_Atomic_Int_FetchAdd(&initRefCount, 1); if (my_initRefCount == 0) { WOLFSSL_ENTER("wolfCrypt_Init"); #if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT) aarch64_use_sb = IS_AARCH64_SB(cpuid_get_flags()); #endif #ifdef WOLFSSL_CHECK_MEM_ZERO /* Initialize the mutex for access to the list of memory locations that * must be freed. */ wc_MemZero_Init(); #endif #ifdef WOLFSSL_MEM_FAIL_COUNT wc_MemFailCount_Init(); #endif #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST { word32 rngMallocFail; time_t seed = time(NULL); srand((word32)seed); rngMallocFail = rand() % 2000; /* max 2000 */ fprintf(stderr, "\n--- RNG MALLOC FAIL AT %u ---\n", rngMallocFail); wolfSSL_SetMemFailCount(rngMallocFail); } #endif #ifdef WOLF_CRYPTO_CB wc_CryptoCb_Init(); #endif #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_HardwareStart(); if (ret != 0) { WOLFSSL_MSG("Async hardware start failed"); /* don't return failure, allow operation to continue */ } #endif #if defined(WOLFSSL_RENESAS_TSIP) ret = tsip_Open( ); if( ret != TSIP_SUCCESS ) { WOLFSSL_MSG("RENESAS TSIP Open failed"); /* not return 1 since WOLFSSL_SUCCESS=1*/ ret = -1;/* FATAL ERROR */ return ret; } #endif #if defined(WOLFSSL_RENESAS_RX64_HASH) ret = rx64_hw_Open(); if( ret != 0 ) { WOLFSSL_MSG("Renesas RX64 HW Open failed"); /* not return 1 since WOLFSSL_SUCCESS=1*/ ret = -1;/* FATAL ERROR */ return ret; } #endif #if defined(WOLFSSL_RENESAS_FSPSM) ret = wc_fspsm_Open( ); if( ret != FSP_SUCCESS ) { WOLFSSL_MSG("RENESAS SCE Open failed"); /* not return 1 since WOLFSSL_SUCCESS=1*/ ret = -1;/* FATAL ERROR */ return ret; } #endif #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) ret = InitMemoryTracker(); if (ret != 0) { WOLFSSL_MSG("InitMemoryTracker failed"); return ret; } #endif #if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WOLFSSL_LINUXKM) ret = allocate_wolfcrypt_linuxkm_fpu_states(); if (ret != 0) { WOLFSSL_MSG("allocate_wolfcrypt_linuxkm_fpu_states failed"); return ret; } #endif #if WOLFSSL_CRYPT_HW_MUTEX /* If crypto hardware mutex protection is enabled, then initialize it */ ret = wolfSSL_CryptHwMutexInit(); if (ret != 0) { WOLFSSL_MSG("Hw crypt mutex init failed"); return ret; } #endif #if defined(HAVE_HASHDRBG) && !defined(WC_NO_RNG) && \ !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) ret = wc_DrbgState_MutexInit(); if (ret != 0) { WOLFSSL_MSG("DRBG state mutex init failed"); return ret; } #endif #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) ret = ksdk_port_init(); if (ret != 0) { WOLFSSL_MSG("KSDK port init failed"); return ret; } #endif /* Crypto Callbacks only works on AES for MAX32666/5 HW */ #if defined(MAX3266X_AES) && defined(WOLF_CRYPTO_CB) ret = wc_CryptoCb_RegisterDevice(WOLFSSL_MAX3266X_DEVID, wc_MxcCryptoCb, NULL); if(ret != 0) { return ret; } #endif #if defined(MAX3266X_RTC) ret = wc_MXC_RTC_Init(); if (ret != 0) { WOLFSSL_MSG("MXC RTC Init Failed"); return WC_HW_E; } #endif #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \ defined(WOLFSSL_ATECC608A) || defined(WOLFSSL_MICROCHIP_TA100) ret = atmel_init(); if (ret != 0) { WOLFSSL_MSG("CryptoAuthLib init failed"); return ret; } #endif #if defined(WOLFSSL_CRYPTOCELL) /* enable and initialize the ARM CryptoCell 3xx runtime library */ ret = cc310_Init(); if (ret != 0) { WOLFSSL_MSG("CRYPTOCELL init failed"); return ret; } #endif #ifdef WOLFSSL_STSAFE ret = stsafe_interface_init(); if (ret != 0) { WOLFSSL_MSG("STSAFE init failed"); return ret; } #endif #if defined(WOLFSSL_TROPIC01) ret = Tropic01_Init(); if (ret != 0) { WOLFSSL_MSG("Tropic01 init failed"); return ret; } #endif #if defined(WOLFSSL_PSOC6_CRYPTO) ret = psoc6_crypto_port_init(); if (ret != 0) { WOLFSSL_MSG("PSoC6 crypto engine init failed"); return ret; } #endif #ifdef MAXQ10XX_MODULE_INIT ret = maxq10xx_port_init(); if (ret != 0) { WOLFSSL_MSG("MAXQ10xx port init failed"); return ret; } #endif #ifdef WOLFSSL_SILABS_SE_ACCEL /* init handles if it is already initialized */ ret = sl_se_init(); #endif #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT) ret = wc_se050_init(NULL); if (ret != 0) { WOLFSSL_MSG("SE050 init failed"); return ret; } #endif #ifdef WOLFSSL_ARMASM WOLFSSL_MSG("Using ARM hardware acceleration"); #endif #ifdef WOLFSSL_AFALG WOLFSSL_MSG("Using AF_ALG for crypto acceleration"); #endif #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) wolfSSL_EVP_init(); #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) if ((ret = wc_LoggingInit()) != 0) { WOLFSSL_MSG("Error creating logging mutex"); return ret; } #endif #if defined(WOLFSSL_HAVE_PSA) if ((ret = wc_psa_init()) != 0) return ret; #endif #if defined(USE_WINDOWS_API) && defined(WIN_REUSE_CRYPT_HANDLE) /* A failure here should not happen, but if it does the actual RNG seed * call will fail. This init is for a shared crypt provider handle for * RNG */ (void)wc_WinCryptHandleInit(); #endif #ifdef HAVE_ENTROPY_MEMUSE ret = Entropy_Init(); if (ret != 0) { WOLFSSL_MSG("Error initializing entropy"); return ret; } #endif #ifdef HAVE_ECC #ifdef FP_ECC wc_ecc_fp_init(); #endif #ifdef ECC_CACHE_CURVE if ((ret = wc_ecc_curve_cache_init()) != 0) { WOLFSSL_MSG("Error creating curve cache"); return ret; } #endif #if defined(HAVE_OID_ENCODING) && (!defined(HAVE_FIPS) || \ (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0))) if ((ret = wc_ecc_oid_cache_init()) != 0) { WOLFSSL_MSG("Error creating ECC oid cache"); return ret; } #endif #endif #ifdef WOLFSSL_SCE ret = (int)WOLFSSL_SCE_GSCE_HANDLE.p_api->open( WOLFSSL_SCE_GSCE_HANDLE.p_ctrl, WOLFSSL_SCE_GSCE_HANDLE.p_cfg); if (ret == SSP_ERR_CRYPTO_SCE_ALREADY_OPEN) { WOLFSSL_MSG("SCE already open"); ret = 0; } if (ret != SSP_SUCCESS) { WOLFSSL_MSG("Error opening SCE"); return -1; /* FATAL_ERROR */ } #endif #if defined(WOLFSSL_DEVCRYPTO) if ((ret = wc_DevCryptoInit()) != 0) { return ret; } #endif #if defined(WOLFSSL_CAAM) if ((ret = wc_caamInit()) != 0) { return ret; } #endif #if defined(HAVE_ARIA) if ((ret = wc_AriaInit()) != 0) { return ret; } #endif #ifdef WOLFSSL_IMXRT_DCP if ((ret = wc_dcp_init()) != 0) { return ret; } #endif #ifdef WOLFSSL_NXP_CASPER if ((ret = wc_casper_init()) != 0) { return ret; } #endif #ifdef WOLFSSL_NXP_HASHCRYPT if ((ret = wc_hashcrypt_init()) != 0) { return ret; } #endif #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) if ((ret = wolfSSL_InitHandle()) != 0) { return ret; } rpcmem_init(); #endif #if defined(HAVE_LIBOQS) if ((ret = wolfSSL_liboqsInit()) != 0) { return ret; } #endif /* increment to 2, to signify successful initialization: */ (void)wolfSSL_Atomic_Int_FetchAdd(&initRefCount, 1); } else { if (my_initRefCount < 2) { (void)wolfSSL_Atomic_Int_FetchSub(&initRefCount, 1); ret = BUSY_E; } } return ret; } #if defined(WOLFSSL_TRACK_MEMORY_VERBOSE) && !defined(WOLFSSL_STATIC_MEMORY) long wolfCrypt_heap_peakAllocs_checkpoint(void) { long ret = ourMemStats.peakAllocsTripOdometer; ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - ourMemStats.totalDeallocs; return ret; } long wolfCrypt_heap_peakBytes_checkpoint(void) { long ret = ourMemStats.peakBytesTripOdometer; ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; return ret; } #endif /* return success value is the same as wolfCrypt_Init */ WOLFSSL_ABI int wolfCrypt_Cleanup(void) { int ret = 0; int my_initRefCount = wolfSSL_Atomic_Int_SubFetch(&initRefCount, 1); if (my_initRefCount == 1) { WOLFSSL_ENTER("wolfCrypt_Cleanup"); #ifdef HAVE_ECC #ifdef FP_ECC wc_ecc_fp_free(); #endif #ifdef ECC_CACHE_CURVE wc_ecc_curve_cache_free(); #endif #if defined(HAVE_OID_ENCODING) && (!defined(HAVE_FIPS) || \ (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0))) wc_ecc_oid_cache_free(); #endif #endif /* HAVE_ECC */ #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) ret = wc_LoggingCleanup(); #endif #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) ShowMemoryTracker(); #endif #ifdef WOLFSSL_ASYNC_CRYPT wolfAsync_HardwareStop(); #endif #ifdef WOLFSSL_RENESAS_TSIP tsip_Close(); #endif #if defined(WOLFSSL_RENESAS_RX64_HASH) rx64_hw_Close(); #endif #if defined(WOLFSSL_RENESAS_FSPSM) wc_fspsm_Close(); #endif #ifdef WOLFSSL_SCE WOLFSSL_SCE_GSCE_HANDLE.p_api->close(WOLFSSL_SCE_GSCE_HANDLE.p_ctrl); #endif #if defined(WOLFSSL_CAAM) wc_caamFree(); #endif #if defined(WOLFSSL_CRYPTOCELL) cc310_Free(); #endif #ifdef WOLFSSL_SILABS_SE_ACCEL ret = sl_se_deinit(); #endif #if defined(WOLFSSL_TROPIC01) Tropic01_Deinit(); #endif #if defined(WOLFSSL_RENESAS_TSIP) tsip_Close(); #endif #if defined(WOLFSSL_DEVCRYPTO) wc_DevCryptoCleanup(); #endif #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) rpcmem_deinit(); wolfSSL_CleanupHandle(); #endif #if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WOLFSSL_LINUXKM) free_wolfcrypt_linuxkm_fpu_states(); #endif #ifdef HAVE_ENTROPY_MEMUSE Entropy_Final(); #endif #if defined(USE_WINDOWS_API) && defined(WIN_REUSE_CRYPT_HANDLE) wc_WinCryptHandleCleanup(); #endif #ifdef WOLF_CRYPTO_CB wc_CryptoCb_Cleanup(); #endif #if defined(HAVE_HASHDRBG) && !defined(WC_NO_RNG) && \ !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) wc_DrbgState_MutexFree(); #endif #if defined(WOLFSSL_MEM_FAIL_COUNT) && defined(WOLFCRYPT_ONLY) wc_MemFailCount_Free(); #endif #ifdef WOLFSSL_CHECK_MEM_ZERO /* Free the mutex for access to the list of memory locations that * must be freed. */ wc_MemZero_Free(); #endif (void)wolfSSL_Atomic_Int_SubFetch(&initRefCount, 1); #if defined(HAVE_LIBOQS) wolfSSL_liboqsClose(); #endif } else if (my_initRefCount < 0) { (void)wolfSSL_Atomic_Int_AddFetch(&initRefCount, 1); WOLFSSL_MSG("wolfCrypt_Cleanup() called with initRefCount <= 0."); ret = ALREADY_E; } return ret; } #ifndef NO_FILESYSTEM /* Helpful function to load file into allocated buffer */ int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, void* heap) { int ret; ssize_t fileSz; XFILE f; if (fname == NULL || buf == NULL || bufLen == NULL) { return BAD_FUNC_ARG; } /* set defaults */ *buf = NULL; *bufLen = 0; /* open file (read-only binary) */ f = XFOPEN(fname, "rb"); if (!f) { WOLFSSL_MSG("wc_LoadFile file load error"); return BAD_PATH_ERROR; } if (XFSEEK(f, 0, XSEEK_END) != 0) { WOLFSSL_MSG("wc_LoadFile file seek error"); XFCLOSE(f); return BAD_PATH_ERROR; } fileSz = XFTELL(f); if (fileSz < 0) { WOLFSSL_MSG("wc_LoadFile ftell error"); XFCLOSE(f); return BAD_PATH_ERROR; } if (XFSEEK(f, 0, XSEEK_SET) != 0) { WOLFSSL_MSG("wc_LoadFile file seek error"); XFCLOSE(f); return BAD_PATH_ERROR; } if (fileSz > 0) { *bufLen = (size_t)fileSz; *buf = (byte*)XMALLOC(*bufLen, heap, DYNAMIC_TYPE_TMP_BUFFER); if (*buf == NULL) { WOLFSSL_MSG("wc_LoadFile memory error"); ret = MEMORY_E; } else { size_t readLen = XFREAD(*buf, 1, *bufLen, f); /* check response code */ ret = (readLen == *bufLen) ? 0 : -1; } } else { ret = BUFFER_E; } XFCLOSE(f); (void)heap; return ret; } #if !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) /* File Handling Helper */ /* returns 0 if file exists, WC_ISFILEEXIST_NOFILE if file doesn't exist */ int wc_FileExists(const char* fname) { struct ReadDirCtx ctx; XMEMSET(&ctx, 0, sizeof(ctx)); if (fname == NULL) return 0; if (XSTAT(fname, &ctx.s) != 0) { WOLFSSL_MSG("stat on name failed"); return BAD_PATH_ERROR; } else { #if defined(USE_WINDOWS_API) if (XS_ISREG(ctx.s.st_mode)) { return 0; } #elif defined(WOLFSSL_ZEPHYR) if (XS_ISREG(ctx.s.type)) { return 0; } #elif defined(WOLFSSL_TELIT_M2MB) if (XS_ISREG(ctx.s.st_mode)) { return 0; } #else if (XS_ISREG(ctx.s.st_mode)) { return 0; } #endif } return WC_ISFILEEXIST_NOFILE; } /* File Handling Helpers */ /* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) { int ret = WC_READDIR_NOFILE; /* default to no files found */ int pathLen = 0; if (name) *name = NULL; if (ctx != NULL) XMEMSET(ctx, 0, sizeof(ReadDirCtx)); if (ctx == NULL || path == NULL) { return BAD_FUNC_ARG; } pathLen = (int)XSTRLEN(path); #ifdef USE_WINDOWS_API if (pathLen > MAX_FILENAME_SZ - 3) return BAD_PATH_ERROR; XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3); XSTRNCPY(ctx->name + pathLen, "\\*", (size_t)(MAX_FILENAME_SZ - pathLen)); ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData); if (ctx->hFind == INVALID_HANDLE_VALUE) { WOLFSSL_MSG("FindFirstFile for path verify locations failed"); return BAD_PATH_ERROR; } do { if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { int dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { return BAD_PATH_ERROR; } XSTRNCPY(ctx->name, path, (size_t)pathLen + 1); ctx->name[pathLen] = '\\'; XSTRNCPY(ctx->name + pathLen + 1, ctx->FindFileData.cFileName, (size_t)(MAX_FILENAME_SZ - pathLen - 1)); if (name) *name = ctx->name; return 0; } } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); #elif defined(INTIME_RTOS) if (pathLen > MAX_FILENAME_SZ - 3) return BAD_PATH_ERROR; XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3); XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen); if (!IntimeFindFirst(ctx->name, &ctx->FindFileData)) { WOLFSSL_MSG("FindFirstFile for path verify locations failed"); return BAD_PATH_ERROR; } do { int dnameLen = (int)XSTRLEN(IntimeFilename(ctx)); if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { return BAD_PATH_ERROR; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '\\'; XSTRNCPY(ctx->name + pathLen + 1, IntimeFilename(ctx), MAX_FILENAME_SZ - pathLen - 1); if (0 == wc_FileExists(ctx->name)) { if (name) *name = ctx->name; return 0; } } while (IntimeFindNext(&ctx->FindFileData)); #elif defined(WOLFSSL_ZEPHYR) if (fs_opendir(&ctx->dir, path) != 0) { WOLFSSL_MSG("opendir path verify locations failed"); return BAD_PATH_ERROR; } ctx->dirp = &ctx->dir; while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { int dnameLen = (int)XSTRLEN(ctx->entry.name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #elif defined(WOLFSSL_TELIT_M2MB) ctx->dir = m2mb_fs_opendir((const CHAR*)path); if (ctx->dir == NULL) { WOLFSSL_MSG("opendir path verify locations failed"); return BAD_PATH_ERROR; } while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { int dnameLen = (int)XSTRLEN(ctx->entry->d_name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #else ctx->dir = opendir(path); if (ctx->dir == NULL) { WOLFSSL_MSG("opendir path verify locations failed"); return BAD_PATH_ERROR; } while ((ctx->entry = readdir(ctx->dir)) != NULL) { int dnameLen = (int)XSTRLEN(ctx->entry->d_name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, (size_t)pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, (size_t)dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #endif wc_ReadDirClose(ctx); return ret; } /* returns 0 if file found, WC_READDIR_NOFILE if no more files */ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) { int ret = WC_READDIR_NOFILE; /* default to no file found */ int pathLen = 0; if (name) *name = NULL; if (ctx == NULL || path == NULL) { return BAD_FUNC_ARG; } XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); pathLen = (int)XSTRLEN(path); #ifdef USE_WINDOWS_API while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) { if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { int dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { return BAD_PATH_ERROR; } XSTRNCPY(ctx->name, path, (size_t)pathLen + 1); ctx->name[pathLen] = '\\'; XSTRNCPY(ctx->name + pathLen + 1, ctx->FindFileData.cFileName, (size_t)(MAX_FILENAME_SZ - pathLen - 1)); if (name) *name = ctx->name; return 0; } } #elif defined(INTIME_RTOS) while (IntimeFindNext(&ctx->FindFileData)) { int dnameLen = (int)XSTRLEN(IntimeFilename(ctx)); if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { return BAD_PATH_ERROR; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '\\'; XSTRNCPY(ctx->name + pathLen + 1, IntimeFilename(ctx), MAX_FILENAME_SZ - pathLen - 1); if (0 == wc_FileExists(ctx->name)) { if (name) *name = ctx->name; return 0; } } #elif defined(WOLFSSL_ZEPHYR) while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { int dnameLen = (int)XSTRLEN(ctx->entry.name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #elif defined(WOLFSSL_TELIT_M2MB) while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { int dnameLen = (int)XSTRLEN(ctx->entry->d_name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #else while ((ctx->entry = readdir(ctx->dir)) != NULL) { int dnameLen = (int)XSTRLEN(ctx->entry->d_name); if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { ret = BAD_PATH_ERROR; break; } XSTRNCPY(ctx->name, path, (size_t)pathLen + 1); ctx->name[pathLen] = '/'; /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, (size_t)dnameLen + 1); if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; } } #endif wc_ReadDirClose(ctx); return ret; } void wc_ReadDirClose(ReadDirCtx* ctx) { if (ctx == NULL) { return; } #ifdef USE_WINDOWS_API if (ctx->hFind != INVALID_HANDLE_VALUE) { FindClose(ctx->hFind); ctx->hFind = INVALID_HANDLE_VALUE; } #elif defined(INTIME_RTOS) IntimeFindClose(&ctx->FindFileData); #elif defined(WOLFSSL_ZEPHYR) if (ctx->dirp) { fs_closedir(ctx->dirp); ctx->dirp = NULL; } #elif defined(WOLFSSL_TELIT_M2MB) if (ctx->dir) { m2mb_fs_closedir(ctx->dir); ctx->dir = NULL; } #else if (ctx->dir) { if (closedir(ctx->dir) < 0) WOLFSSL_MSG("closedir() failed"); ctx->dir = NULL; } #endif } #endif /* !NO_WOLFSSL_DIR */ #endif /* !NO_FILESYSTEM */ #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR) XFILE z_fs_open(const char* filename, const char* mode) { XFILE file; fs_mode_t flags = 0; if (mode == NULL) return NULL; /* Parse mode */ switch (*mode++) { case 'r': flags |= FS_O_READ; break; case 'w': flags |= FS_O_WRITE|FS_O_CREATE; break; case 'a': flags |= FS_O_APPEND|FS_O_CREATE; break; default: return NULL; } /* Ignore binary flag */ if (*mode == 'b') mode++; if (*mode == '+') { flags |= FS_O_READ; /* Don't add write flag if already appending */ if (!(flags & FS_O_APPEND)) flags |= FS_O_RDWR; } /* Ignore binary flag */ if (*mode == 'b') mode++; /* Incorrect mode string */ if (*mode != '\0') return NULL; file = (XFILE)XMALLOC(sizeof(*file), NULL, DYNAMIC_TYPE_FILE); if (file != NULL) { fs_file_t_init(file); if (fs_open(file, filename, flags) != 0) { XFREE(file, NULL, DYNAMIC_TYPE_FILE); file = NULL; } } return file; } int z_fs_close(XFILE file) { int ret; if (file == NULL) return -1; ret = (fs_close(file) == 0) ? 0 : -1; XFREE(file, NULL, DYNAMIC_TYPE_FILE); return ret; } /* Rewind the file pointer to the beginning of the file */ /* This is not a 'rewind' is not supported in Zephyr so */ /* use fs_seek to move the file pointer to the beginning of the file */ /* calling it z_fs_rewind to avoid future conflicts if rewind is added */ int z_fs_rewind(XFILE file) { return fs_seek(file, 0, FS_SEEK_SET); } #endif /* !NO_FILESYSTEM && !WOLFSSL_ZEPHYR */ #if !defined(WOLFSSL_USER_MUTEX) wolfSSL_Mutex* wc_InitAndAllocMutex(void) { wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL, DYNAMIC_TYPE_MUTEX); if (m != NULL) { if (wc_InitMutex(m) != 0) { WOLFSSL_MSG("Init Mutex failed"); XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); m = NULL; } } else { WOLFSSL_MSG("Memory error with Mutex allocation"); } return m; } #endif #ifdef USE_WOLF_STRTOK /* String token (delim) search. If str is null use nextp. */ char* wc_strtok(char *str, const char *delim, char **nextp) { char* ret; int i, j; /* Use next if str is NULL */ if (str == NULL && nextp) str = *nextp; /* verify str input */ if (str == NULL || *str == '\0') return NULL; /* match on entire delim */ for (i = 0; str[i]; i++) { for (j = 0; delim[j]; j++) { if (delim[j] == str[i]) break; } if (!delim[j]) break; } str += i; /* if end of string, not found so return NULL */ if (*str == '\0') return NULL; ret = str; /* match on first delim */ for (i = 0; str[i]; i++) { for (j = 0; delim[j]; j++) { if (delim[j] == str[i]) break; } if (delim[j] == str[i]) break; } str += i; /* null terminate found string */ if (*str) *str++ = '\0'; /* return pointer to next */ if (nextp) *nextp = str; return ret; } #endif /* USE_WOLF_STRTOK */ #ifdef USE_WOLF_STRSEP char* wc_strsep(char **stringp, const char *delim) { char *s, *tok; const char *spanp; /* null check */ if (stringp == NULL || *stringp == NULL) return NULL; s = *stringp; for (tok = s; *tok; ++tok) { for (spanp = delim; *spanp; ++spanp) { /* found delimiter */ if (*tok == *spanp) { *tok = '\0'; /* replace delim with null term */ *stringp = tok + 1; /* return past delim */ return s; } } } *stringp = NULL; return s; } #endif /* USE_WOLF_STRSEP */ #ifdef USE_WOLF_STRLCPY size_t wc_strlcpy(char *dst, const char *src, size_t dstSize) { size_t i; if (!dstSize) return 0; /* Always have to leave a space for NULL */ for (i = 0; i < (dstSize - 1) && *src != '\0'; i++) { *dst++ = *src++; } *dst = '\0'; return i; /* return length without NULL */ } #endif /* USE_WOLF_STRLCPY */ #ifdef USE_WOLF_STRLCAT size_t wc_strlcat(char *dst, const char *src, size_t dstSize) { size_t dstLen; if (!dstSize) return 0; dstLen = XSTRLEN(dst); if (dstSize < dstLen) return dstLen + XSTRLEN(src); return dstLen + wc_strlcpy(dst + dstLen, src, dstSize - dstLen); } #endif /* USE_WOLF_STRLCAT */ #ifdef USE_WOLF_STRCASECMP int wc_strcasecmp(const char *s1, const char *s2) { char c1, c2; for (;;++s1, ++s2) { c1 = *s1; if ((c1 >= 'a') && (c1 <= 'z')) c1 = (char)(c1 - ('a' - 'A')); c2 = *s2; if ((c2 >= 'a') && (c2 <= 'z')) c2 = (char)(c2 - ('a' - 'A')); if ((c1 != c2) || (c1 == 0)) break; } return (c1 - c2); } #endif /* USE_WOLF_STRCASECMP */ #ifdef USE_WOLF_STRNCASECMP int wc_strncasecmp(const char *s1, const char *s2, size_t n) { char c1, c2; for (c1 = 0, c2 = 0; n > 0; --n, ++s1, ++s2) { c1 = *s1; if ((c1 >= 'a') && (c1 <= 'z')) c1 = (char)(c1 - ('a' - 'A')); c2 = *s2; if ((c2 >= 'a') && (c2 <= 'z')) c2 = (char)(c2 - ('a' - 'A')); if ((c1 != c2) || (c1 == 0)) break; } return (c1 - c2); } #endif /* USE_WOLF_STRNCASECMP */ #ifdef USE_WOLF_STRDUP char* wc_strdup_ex(const char *src, int memType) { char *ret = NULL; word32 len = 0; if (src) { len = (word32)XSTRLEN(src) + 1; /* Add one for null terminator */ ret = (char*)XMALLOC(len, NULL, memType); if (ret != NULL) { XMEMCPY(ret, src, len); } } return ret; } #endif #ifdef WOLFSSL_ATOMIC_OPS #if defined(WOLFSSL_USER_DEFINED_ATOMICS) #elif defined(SINGLE_THREADED) #elif defined(WOLFSSL_BSDKM) /* Note: using compiler built-ins like __atomic_fetch_add will technically * build in FreeBSD kernel, but are not commonly used in FreeBSD kernel and * might not be safe or portable. * */ void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i) { *c = i; } void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, unsigned int i) { *c = i; } int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i) { return atomic_fetchadd_int(c, i); } int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i) { return atomic_fetchadd_int(c, -i); } int wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c, int i) { int val = atomic_fetchadd_int(c, i); return val + i; } int wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c, int i) { int val = atomic_fetchadd_int(c, -i); return val - i; } unsigned int wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c, unsigned int i) { return atomic_fetchadd_int(c, i); } unsigned int wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c, unsigned int i) { return atomic_fetchadd_int(c, -i); } unsigned int wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int val = atomic_fetchadd_int(c, i); return val + i; } unsigned int wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int val = atomic_fetchadd_int(c, -i); return val - i; } int wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c, int new_i) { return atomic_swap_int(c, new_i); } int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c, int *expected_i, int new_i) { u_int exp = (u_int) *expected_i; int ret = atomic_fcmpset_int(c, &exp, new_i); *expected_i = (int)exp; return ret; } int wolfSSL_Atomic_Uint_CompareExchange( wolfSSL_Atomic_Uint* c, unsigned int *expected_i, unsigned int new_i) { u_int exp = (u_int)*expected_i; int ret = atomic_fcmpset_int(c, &exp, new_i); *expected_i = (unsigned int)exp; return ret; } int wolfSSL_Atomic_Ptr_CompareExchange( void * volatile *c, void **expected_ptr, void *new_ptr) { uintptr_t exp = (uintptr_t)*expected_ptr; int ret = atomic_fcmpset_ptr((uintptr_t *)c, &exp, (uintptr_t)new_ptr); *expected_ptr = (void *)exp; return ret; } #elif defined(HAVE_C___ATOMIC) && defined(WOLFSSL_HAVE_ATOMIC_H) && \ !defined(__cplusplus) /* Default C Implementation */ void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i) { atomic_init(c, i); } void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, unsigned int i) { atomic_init(c, i); } int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i) { return atomic_fetch_add_explicit(c, i, memory_order_relaxed); } int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i) { return atomic_fetch_sub_explicit(c, i, memory_order_relaxed); } int wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c, int i) { int ret = atomic_fetch_add_explicit(c, i, memory_order_relaxed); return ret + i; } int wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c, int i) { int ret = atomic_fetch_sub_explicit(c, i, memory_order_relaxed); return ret - i; } int wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c, int new_i) { return atomic_exchange_explicit(c, new_i, memory_order_seq_cst); } int wolfSSL_Atomic_Int_CompareExchange( wolfSSL_Atomic_Int* c, int *expected_i, int new_i) { /* For the success path, use full synchronization with barriers -- * "Sequentially-consistent ordering" -- so that all threads see the same * "single total modification order of all atomic operations" -- but on * failure we just need to be sure we acquire the value that changed out * from under us. */ return atomic_compare_exchange_strong_explicit( c, expected_i, new_i, memory_order_seq_cst, memory_order_acquire); } unsigned int wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c, unsigned int i) { return atomic_fetch_add_explicit(c, i, memory_order_relaxed); } unsigned int wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c, unsigned int i) { return atomic_fetch_sub_explicit(c, i, memory_order_relaxed); } unsigned int wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int ret = atomic_fetch_add_explicit(c, i, memory_order_relaxed); return ret + i; } unsigned int wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int ret = atomic_fetch_sub_explicit(c, i, memory_order_relaxed); return ret - i; } int wolfSSL_Atomic_Uint_CompareExchange( wolfSSL_Atomic_Uint* c, unsigned int *expected_i, unsigned int new_i) { /* For the success path, use full synchronization with barriers -- * "Sequentially-consistent ordering" -- so that all threads see the same * "single total modification order of all atomic operations" -- but on * failure we just need to be sure we acquire the value that changed out * from under us. */ return atomic_compare_exchange_strong_explicit( c, expected_i, new_i, memory_order_seq_cst, memory_order_acquire); } int wolfSSL_Atomic_Ptr_CompareExchange( void * volatile *c, void **expected_ptr, void *new_ptr) { /* use gcc-built-in __atomic_compare_exchange_n(), not * atomic_compare_exchange_strong_explicit(), to sidestep _Atomic type * requirements. */ if (__atomic_compare_exchange_n( c, expected_ptr, new_ptr, #ifdef WOLF_C89 0 /* weak */, #else (_Bool)0 /* weak */, #endif __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)) return 1; else return 0; } #elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) /* direct calls using gcc-style compiler built-ins */ void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i) { *c = i; } void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, unsigned int i) { *c = i; } int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i) { return __atomic_fetch_add(c, i, __ATOMIC_RELAXED); } int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i) { return __atomic_fetch_sub(c, i, __ATOMIC_RELAXED); } int wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c, int i) { return __atomic_add_fetch(c, i, __ATOMIC_RELAXED); } int wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c, int i) { return __atomic_sub_fetch(c, i, __ATOMIC_RELAXED); } int wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c, int new_i) { return __atomic_exchange_n(c, new_i, __ATOMIC_SEQ_CST); } int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c, int *expected_i, int new_i) { /* For the success path, use full synchronization with barriers -- * "Sequentially-consistent ordering" -- so that all threads see the same * "single total modification order of all atomic operations" -- but on * failure we just need to be sure we acquire the value that changed out * from under us. */ return __atomic_compare_exchange_n(c, expected_i, new_i, 0 /* weak */, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); } unsigned int wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c, unsigned int i) { return __atomic_fetch_add(c, i, __ATOMIC_RELAXED); } unsigned int wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c, unsigned int i) { return __atomic_fetch_sub(c, i, __ATOMIC_RELAXED); } unsigned int wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { return __atomic_add_fetch(c, i, __ATOMIC_RELAXED); } unsigned int wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { return __atomic_sub_fetch(c, i, __ATOMIC_RELAXED); } int wolfSSL_Atomic_Uint_CompareExchange( wolfSSL_Atomic_Uint* c, unsigned int *expected_i, unsigned int new_i) { /* For the success path, use full synchronization with barriers -- * "Sequentially-consistent ordering" -- so that all threads see the same * "single total modification order of all atomic operations" -- but on * failure we just need to be sure we acquire the value that changed out * from under us. */ return __atomic_compare_exchange_n( c, expected_i, new_i, 0 /* weak */, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); } int wolfSSL_Atomic_Ptr_CompareExchange( void * volatile *c, void **expected_ptr, void *new_ptr) { return __atomic_compare_exchange_n( c, expected_ptr, new_ptr, 0 /* weak */, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); } #elif defined(_MSC_VER) && !defined(WOLFSSL_NOT_WINDOWS_API) void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, int i) { *c = i; } void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, unsigned int i) { *c = i; } int wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c, int i) { return (int)_InterlockedExchangeAdd(c, (long)i); } int wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c, int i) { return (int)_InterlockedExchangeAdd(c, (long)-i); } int wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c, int i) { int ret = (int)_InterlockedExchangeAdd(c, (long)i); return ret + i; } int wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c, int i) { int ret = (int)_InterlockedExchangeAdd(c, (long)-i); return ret - i; } int wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c, int new_i) { long actual_i = InterlockedExchange(c, (long)new_i); return (int)actual_i; } int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c, int *expected_i, int new_i) { long actual_i = InterlockedCompareExchange(c, (long)new_i, (long)*expected_i); if (actual_i == (long)*expected_i) { return 1; } else { *expected_i = (int)actual_i; return 0; } } unsigned int wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c, unsigned int i) { return (unsigned int)_InterlockedExchangeAdd((wolfSSL_Atomic_Int *)c, (long)i); } unsigned int wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c, unsigned int i) { return (unsigned int)_InterlockedExchangeAdd((wolfSSL_Atomic_Int *)c, -(long)i); } unsigned int wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int ret = (unsigned int)_InterlockedExchangeAdd ((wolfSSL_Atomic_Int *)c, (long)i); return ret + i; } unsigned int wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c, unsigned int i) { unsigned int ret = (unsigned int)_InterlockedExchangeAdd ((wolfSSL_Atomic_Int *)c, -(long)i); return ret - i; } int wolfSSL_Atomic_Uint_CompareExchange( wolfSSL_Atomic_Uint* c, unsigned int *expected_i, unsigned int new_i) { long actual_i = InterlockedCompareExchange( (wolfSSL_Atomic_Int *)c, (long)new_i, (long)*expected_i); if (actual_i == (long)*expected_i) { return 1; } else { *expected_i = (unsigned int)actual_i; return 0; } } int wolfSSL_Atomic_Ptr_CompareExchange( void * volatile * c, void **expected_ptr, void *new_ptr) { #ifdef _WIN64 LONG64 actual_ptr = InterlockedCompareExchange64( (LONG64 *)c, (LONG64)new_ptr, (LONG64)*expected_ptr); if (actual_ptr == (LONG64)*expected_ptr) { return 1; } else { *expected_ptr = (void *)actual_ptr; return 0; } #else /* !_WIN64 */ LONG actual_ptr = InterlockedCompareExchange( (LONG *)c, (LONG)new_ptr, (LONG)*expected_ptr); if (actual_ptr == (LONG)*expected_ptr) { return 1; } else { *expected_ptr = (void *)actual_ptr; return 0; } #endif /* !_WIN64 */ } #endif #endif /* WOLFSSL_ATOMIC_OPS */ #if !defined(SINGLE_THREADED) void wolfSSL_RefWithMutexInit(wolfSSL_RefWithMutex* ref, int* err) { int ret = wc_InitMutex(&ref->mutex); if (ret != 0) { WOLFSSL_MSG("Failed to create mutex for reference counting!"); } ref->count = 1; *err = ret; } void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref) { if (wc_FreeMutex(&ref->mutex) != 0) { WOLFSSL_MSG("Failed to free mutex of reference counting!"); } ref->count = 0; } void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { WOLFSSL_MSG("Failed to lock mutex for reference increment!"); } else { ref->count++; wc_UnLockMutex(&ref->mutex); } *err = ret; } void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref, int *new_count, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { WOLFSSL_MSG("Failed to lock mutex for reference increment!"); *new_count = -1; } else { *new_count = ++ref->count; wc_UnLockMutex(&ref->mutex); } *err = ret; } int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref) { return wc_LockMutex(&ref->mutex); } int wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref) { return wc_UnLockMutex(&ref->mutex); } void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, int* isZero, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { WOLFSSL_MSG("Failed to lock mutex for reference decrement!"); /* Can't say count is zero. */ *isZero = 0; } else { if (ref->count > 0) { ref->count--; } *isZero = (ref->count == 0); wc_UnLockMutex(&ref->mutex); } *err = ret; } void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref, int* new_count, int* err) { int ret = wc_LockMutex(&ref->mutex); if (ret != 0) { WOLFSSL_MSG("Failed to lock mutex for reference decrement!"); *new_count = -1; } else { if (ref->count > 0) { ref->count--; } *new_count = ref->count; wc_UnLockMutex(&ref->mutex); } *err = ret; } #endif /* ! SINGLE_THREADED */ #if WOLFSSL_CRYPT_HW_MUTEX /* Mutex for protection of cryptography hardware */ static wolfSSL_Mutex wcCryptHwMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwMutex); #ifndef WOLFSSL_MUTEX_INITIALIZER static int wcCryptHwMutexInit = 0; #endif int wolfSSL_CryptHwMutexInit(void) { int ret = 0; #ifndef WOLFSSL_MUTEX_INITIALIZER if (wcCryptHwMutexInit == 0) { ret = wc_InitMutex(&wcCryptHwMutex); if (ret == 0) { wcCryptHwMutexInit = 1; } } #endif return ret; } int wolfSSL_CryptHwMutexLock(void) { /* Make sure HW Mutex has been initialized */ int ret = wolfSSL_CryptHwMutexInit(); if (ret == 0) { ret = wc_LockMutex(&wcCryptHwMutex); } return ret; } int wolfSSL_CryptHwMutexUnLock(void) { if (wcCryptHwMutexInit) { return wc_UnLockMutex(&wcCryptHwMutex); } else { return BAD_MUTEX_E; } } #endif /* WOLFSSL_CRYPT_HW_MUTEX */ #if WOLFSSL_CRYPT_HW_MUTEX && defined(WOLFSSL_ALGO_HW_MUTEX) /* Mutex for protection of cryptography hardware */ #ifndef NO_RNG_MUTEX static wolfSSL_Mutex wcCryptHwRngMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwRngMutex); #endif /* NO_RNG_MUTEX */ #ifndef NO_AES_MUTEX static wolfSSL_Mutex wcCryptHwAesMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwAesMutex); #endif /* NO_AES_MUTEX */ #ifndef NO_HASH_MUTEX static wolfSSL_Mutex wcCryptHwHashMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwHashMutex); #endif /* NO_HASH_MUTEX */ #ifndef NO_PK_MUTEX static wolfSSL_Mutex wcCryptHwPkMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwPkMutex); #endif /* NO_PK_MUTEX */ #ifndef WOLFSSL_MUTEX_INITIALIZER #ifndef NO_RNG_MUTEX static int wcCryptHwRngMutexInit = 0; #endif /* NO_RNG_MUTEX */ #ifndef NO_AES_MUTEX static int wcCryptHwAesMutexInit = 0; #endif /* NO_AES_MUTEX */ #ifndef NO_HASH_MUTEX static int wcCryptHwHashMutexInit = 0; #endif /* NO_HASH_MUTEX */ #ifndef NO_PK_MUTEX static int wcCryptHwPkMutexInit = 0; #endif /* NO_PK_MUTEX */ #endif /* WOLFSSL_MUTEX_INITIALIZER */ /* Allows ability to switch to different mutex based on enum type */ /* hw_mutex_algo, expects the dereferenced Ptrs to be set to NULL */ static int hwAlgoPtrSet(hw_mutex_algo hwAlgo, wolfSSL_Mutex** wcHwAlgoMutexPtr, int** wcHwAlgoInitPtr) { if (*wcHwAlgoMutexPtr != NULL || *wcHwAlgoInitPtr != NULL) { return BAD_FUNC_ARG; } switch (hwAlgo) { #ifndef NO_RNG_MUTEX case rng_mutex: *wcHwAlgoMutexPtr = &wcCryptHwRngMutex; *wcHwAlgoInitPtr = &wcCryptHwRngMutexInit; break; #endif #ifndef NO_AES_MUTEX case aes_mutex: *wcHwAlgoMutexPtr = &wcCryptHwAesMutex; *wcHwAlgoInitPtr = &wcCryptHwAesMutexInit; break; #endif #ifndef NO_HASH_MUTEX case hash_mutex: *wcHwAlgoMutexPtr = &wcCryptHwHashMutex; *wcHwAlgoInitPtr = &wcCryptHwHashMutexInit; break; #endif #ifndef NO_PK_MUTEX case pk_mutex: *wcHwAlgoMutexPtr = &wcCryptHwPkMutex; *wcHwAlgoInitPtr = &wcCryptHwPkMutexInit; break; #endif default: return BAD_FUNC_ARG; } return 0; } static int hwAlgoMutexInit(hw_mutex_algo hwAlgo) { int ret = 0; #ifndef WOLFSSL_MUTEX_INITIALIZER wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL; int* wcHwAlgoInitPtr = NULL; ret = hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr); if (ret != 0) { return ret; } if (*wcHwAlgoInitPtr == 0) { ret = wc_InitMutex(wcHwAlgoMutexPtr); if (ret == 0) { *wcHwAlgoInitPtr = 1; } } #endif return ret; } static int hwAlgoMutexLock(hw_mutex_algo hwAlgo) { /* Make sure HW Mutex has been initialized */ int ret = 0; wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL; int* wcHwAlgoInitPtr = NULL; ret = hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr); if (ret != 0) { return ret; } ret = hwAlgoMutexInit(hwAlgo); if (ret == 0) { ret = wc_LockMutex(wcHwAlgoMutexPtr); } return ret; } static int hwAlgoMutexUnLock(hw_mutex_algo hwAlgo) { wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL; int* wcHwAlgoInitPtr = NULL; if (hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr) != 0) { return BAD_FUNC_ARG; } if (*wcHwAlgoInitPtr) { return wc_UnLockMutex(wcHwAlgoMutexPtr); } else { return BAD_MUTEX_E; } } /* Wrap around generic hwAlgo* functions and use correct */ /* global mutex to determine if it can be unlocked/locked */ #ifndef NO_RNG_MUTEX int wolfSSL_HwRngMutexInit(void) { return hwAlgoMutexInit(rng_mutex); } int wolfSSL_HwRngMutexLock(void) { return hwAlgoMutexLock(rng_mutex); } int wolfSSL_HwRngMutexUnLock(void) { return hwAlgoMutexUnLock(rng_mutex); } #endif /* NO_RNG_MUTEX */ #ifndef NO_AES_MUTEX int wolfSSL_HwAesMutexInit(void) { return hwAlgoMutexInit(aes_mutex); } int wolfSSL_HwAesMutexLock(void) { return hwAlgoMutexLock(aes_mutex); } int wolfSSL_HwAesMutexUnLock(void) { return hwAlgoMutexUnLock(aes_mutex); } #endif /* NO_AES_MUTEX */ #ifndef NO_HASH_MUTEX int wolfSSL_HwHashMutexInit(void) { return hwAlgoMutexInit(hash_mutex); } int wolfSSL_HwHashMutexLock(void) { return hwAlgoMutexLock(hash_mutex); } int wolfSSL_HwHashMutexUnLock(void) { return hwAlgoMutexUnLock(hash_mutex); } #endif /* NO_HASH_MUTEX */ #ifndef NO_PK_MUTEX int wolfSSL_HwPkMutexInit(void) { return hwAlgoMutexInit(pk_mutex); } int wolfSSL_HwPkMutexLock(void) { return hwAlgoMutexLock(pk_mutex); } int wolfSSL_HwPkMutexUnLock(void) { return hwAlgoMutexUnLock(pk_mutex); } #endif /* NO_PK_MUTEX */ #endif /* WOLFSSL_CRYPT_HW_MUTEX && defined(WOLFSSL_ALGO_HW_MUTEX) */ /* ---------------------------------------------------------------------------*/ /* Mutex Ports */ /* ---------------------------------------------------------------------------*/ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) static mutex_cb* compat_mutex_cb = NULL; /* Function that locks or unlocks a mutex based on the flag passed in. * * flag lock or unlock i.e. CRYPTO_LOCK * type the type of lock to unlock or lock * file name of the file calling * line the line number from file calling */ int wc_LockMutex_ex(int flag, int type, const char* file, int line) { if (compat_mutex_cb != NULL) { compat_mutex_cb(flag, type, file, line); return 0; } else { WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb"); return BAD_STATE_E; } } /* Set the callback function to use for locking/unlocking mutex * * cb callback function to use */ int wc_SetMutexCb(mutex_cb* cb) { compat_mutex_cb = cb; return 0; } /* Gets the current callback function in use for locking/unlocking mutex * */ mutex_cb* wc_GetMutexCb(void) { return compat_mutex_cb; } #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */ #if defined(WC_MUTEX_OPS_INLINE) /* defined in headers */ #elif defined(SINGLE_THREADED) int wc_InitMutex(wolfSSL_Mutex* m) { (void)m; return 0; } int wc_FreeMutex(wolfSSL_Mutex *m) { (void)m; return 0; } int wc_LockMutex(wolfSSL_Mutex *m) { (void)m; return 0; } int wc_UnLockMutex(wolfSSL_Mutex *m) { (void)m; return 0; } #elif defined(__WATCOMC__) int wc_InitMutex(wolfSSL_Mutex* m) { #ifdef __OS2__ DosCreateMutexSem( NULL, m, 0, FALSE ); #elif defined(__NT__) InitializeCriticalSection(m); #elif defined(__LINUX__) if (pthread_mutex_init(m, NULL) ) return BAD_MUTEX_E; #endif return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { #ifdef __OS2__ DosCloseMutexSem(*m); #elif defined(__NT__) DeleteCriticalSection(m); #elif defined(__LINUX__) if (pthread_mutex_destroy(m) ) return BAD_MUTEX_E; #endif return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { #ifdef __OS2__ DosRequestMutexSem(*m, SEM_INDEFINITE_WAIT); #elif defined(__NT__) EnterCriticalSection(m); #elif defined(__LINUX__) if (pthread_mutex_lock(m) ) return BAD_MUTEX_E; #endif return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { #ifdef __OS2__ DosReleaseMutexSem(*m); #elif defined(__NT__) LeaveCriticalSection(m); #elif defined(__LINUX__) if (pthread_mutex_unlock(m) ) return BAD_MUTEX_E; #endif return 0; } #if defined(WOLFSSL_USE_RWLOCK) && defined(__LINUX__) int wc_InitRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_init(m, NULL) ) return BAD_MUTEX_E; return 0; } int wc_FreeRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_destroy(m) ) return BAD_MUTEX_E; return 0; } int wc_LockRwLock_Wr(wolfSSL_RwLock* m) { if (pthread_rwlock_wrlock(m) ) return BAD_MUTEX_E; return 0; } int wc_LockRwLock_Rd(wolfSSL_RwLock* m) { if (pthread_rwlock_rdlock(m) ) return BAD_MUTEX_E; return 0; } int wc_UnLockRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_unlock(m) == 0) return BAD_MUTEX_E; return 0; } #endif #elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ defined(FREESCALE_FREE_RTOS) int wc_InitMutex(wolfSSL_Mutex* m) { int iReturn; *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); if( *m != NULL ) iReturn = 0; else iReturn = BAD_MUTEX_E; return iReturn; } int wc_FreeMutex(wolfSSL_Mutex* m) { vSemaphoreDelete( *m ); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { /* Assume an infinite block, or should there be zero block? */ xSemaphoreTake( *m, portMAX_DELAY ); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { xSemaphoreGive( *m ); return 0; } #elif defined(RTTHREAD) int wc_InitMutex(wolfSSL_Mutex* m) { int iReturn; *m = ( wolfSSL_Mutex ) rt_mutex_create("mutex",RT_IPC_FLAG_FIFO); if( *m != NULL ) iReturn = 0; else iReturn = BAD_MUTEX_E; return iReturn; } int wc_FreeMutex(wolfSSL_Mutex* m) { rt_mutex_delete( *m ); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { /* Assume an infinite block, or should there be zero block? */ return rt_mutex_take( *m, RT_WAITING_FOREVER ); } int wc_UnLockMutex(wolfSSL_Mutex* m) { return rt_mutex_release( *m ); } #elif defined(WOLFSSL_SAFERTOS) int wc_InitMutex(wolfSSL_Mutex* m) { vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); if (m->mutex == NULL) return BAD_MUTEX_E; return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { (void)m; return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { /* Assume an infinite block */ xSemaphoreTake(m->mutex, portMAX_DELAY); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { xSemaphoreGive(m->mutex); return 0; } #elif defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS) int wc_InitMutex(wolfSSL_Mutex* m) { InitializeCriticalSection(m); return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { DeleteCriticalSection(m); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { EnterCriticalSection(m); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { LeaveCriticalSection(m); return 0; } #elif defined(MAXQ10XX_MUTEX) static pthread_mutex_t *wcCryptHwSharedMutexPtr; static pthread_once_t key_once_own_hw_mutex = PTHREAD_ONCE_INIT; static pthread_key_t key_own_hw_mutex; static void destruct_key(void *buf) { if (buf != NULL) { XFREE(buf, NULL, DYNAMIC_TYPE_OS_BUF); } } static void make_key_own_hw_mutex(void) { (void)pthread_key_create(&key_own_hw_mutex, destruct_key); } int wc_InitMutex(wolfSSL_Mutex* m) { int created = 0; void *addr = NULL; if (m != &wcCryptHwMutex) { if (pthread_mutex_init(m, 0) == 0) { return 0; } return BAD_MUTEX_E; } /* try to open mutex memory */ int shm_fd = shm_open("/maxq-mutex", O_RDWR, 0666); if (shm_fd < 0) { /* create mutex memory */ shm_fd = shm_open("/maxq-mutex", O_RDWR | O_CREAT | O_EXCL, 0666); created = 1; } if (shm_fd < 0) { WOLFSSL_MSG("wc_InitMutex: shm_open() failed"); return BAD_MUTEX_E; } if (ftruncate(shm_fd, sizeof(pthread_mutex_t))) { WOLFSSL_MSG("wc_InitMutex: ftruncate() failed"); return BAD_MUTEX_E; } addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (addr == MAP_FAILED) { WOLFSSL_MSG("wc_InitMutex: mmap() failed"); return BAD_MUTEX_E; } wcCryptHwSharedMutexPtr = (pthread_mutex_t *)addr; if (close(shm_fd)) { WOLFSSL_MSG("wc_InitMutex: close() failed"); return BAD_MUTEX_E; } if (created) { /* initialize mutex */ pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr)) { WOLFSSL_MSG("wc_InitMutex: pthread_mutexattr_init() failed"); return BAD_MUTEX_E; } if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { WOLFSSL_MSG( "wc_InitMutex: pthread_mutexattr_setpshared() failed"); return BAD_MUTEX_E; } if (pthread_mutex_init(wcCryptHwSharedMutexPtr, &attr)) { WOLFSSL_MSG("wc_InitMutex: pthread_mutex_init() failed"); return BAD_MUTEX_E; } } if (pthread_once(&key_once_own_hw_mutex, make_key_own_hw_mutex)) { WOLFSSL_MSG("wc_InitMutex: pthread_once() failed"); return BAD_MUTEX_E; } return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { void *key_ptr = NULL; if (m != &wcCryptHwMutex) { if (pthread_mutex_destroy(m) == 0) { return 0; } return BAD_MUTEX_E; } if (wcCryptHwSharedMutexPtr) { if (munmap((void *)wcCryptHwSharedMutexPtr, sizeof(pthread_mutex_t))) { WOLFSSL_MSG("wc_FreeMutex: munmap() failed"); return BAD_MUTEX_E; } wcCryptHwSharedMutexPtr = NULL; } key_ptr = pthread_getspecific(key_own_hw_mutex); if (key_ptr) { *((int *)key_ptr) = 0; } return 0; } static int maxq_LockMutex(wolfSSL_Mutex* m, int trylock) { void *key_ptr = NULL; int ret = 0; if (m != &wcCryptHwMutex) { if (pthread_mutex_lock(m) == 0) { return 0; } return BAD_MUTEX_E; } if (wcCryptHwSharedMutexPtr == NULL) { return BAD_MUTEX_E; } key_ptr = pthread_getspecific(key_own_hw_mutex); if (key_ptr == NULL) { key_ptr = XMALLOC(sizeof(int), NULL, DYNAMIC_TYPE_OS_BUF); if (key_ptr == NULL) { return MEMORY_E; } memset(key_ptr, 0, sizeof(int)); if (pthread_setspecific(key_own_hw_mutex, key_ptr)) { return THREAD_STORE_SET_E; } } else { if ((trylock == 0) && (*((int *)key_ptr) > 0)) { *((int *)key_ptr) = *((int *)key_ptr) + 1; return 0; } } if (trylock) { ret = pthread_mutex_trylock(wcCryptHwSharedMutexPtr); } else { ret = pthread_mutex_lock(wcCryptHwSharedMutexPtr); } if (ret != 0) { return BAD_MUTEX_E; } *((int *)key_ptr) = 1; return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { return maxq_LockMutex(m, 0); } int maxq_CryptHwMutexTryLock() { /* Make sure HW Mutex has been initialized */ int ret = wolfSSL_CryptHwMutexInit(); if (ret == 0) { ret = maxq_LockMutex(&wcCryptHwMutex, 1); } return ret; } int wc_UnLockMutex(wolfSSL_Mutex* m) { void *key_ptr = NULL; if (m != &wcCryptHwMutex) { if (pthread_mutex_unlock(m) == 0) { return 0; } return BAD_MUTEX_E; } if (wcCryptHwSharedMutexPtr == NULL) { return BAD_MUTEX_E; } key_ptr = pthread_getspecific(key_own_hw_mutex); if (key_ptr) { if (*((int *)key_ptr) > 0) { *((int *)key_ptr) = *((int *)key_ptr) - 1; if (*((int *)key_ptr) > 0) { return 0; } } } if (pthread_mutex_unlock(wcCryptHwSharedMutexPtr) != 0) { return BAD_MUTEX_E; } return 0; } #elif defined(WOLFSSL_PTHREADS) #ifdef WOLFSSL_USE_RWLOCK int wc_InitRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_init(m, NULL) == 0) return 0; else return BAD_MUTEX_E; } int wc_FreeRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_destroy(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_LockRwLock_Wr(wolfSSL_RwLock* m) { if (pthread_rwlock_wrlock(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_LockRwLock_Rd(wolfSSL_RwLock* m) { if (pthread_rwlock_rdlock(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_UnLockRwLock(wolfSSL_RwLock* m) { if (pthread_rwlock_unlock(m) == 0) return 0; else return BAD_MUTEX_E; } #endif int wc_InitMutex(wolfSSL_Mutex* m) { if (pthread_mutex_init(m, NULL) == 0) return 0; else return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { if (pthread_mutex_destroy(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { if (pthread_mutex_lock(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { if (pthread_mutex_unlock(m) == 0) return 0; else return BAD_MUTEX_E; } #elif defined(WOLFSSL_VXWORKS) int wc_InitMutex(wolfSSL_Mutex* m) { if (m) { if ((*m = semMCreate(0)) != SEM_ID_NULL) return 0; } return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { if (m) { if (semDelete(*m) == OK) return 0; } return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { if (m) { if (semTake(*m, WAIT_FOREVER) == OK) return 0; } return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { if (m) { if (semGive(*m) == OK) return 0; } return BAD_MUTEX_E; } #elif defined(THREADX) int wc_InitMutex(wolfSSL_Mutex* m) { if (tx_mutex_create(m, (CHAR*)"wolfSSL Mutex", TX_NO_INHERIT) == 0) return 0; else return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { if (tx_mutex_delete(m) == 0) return 0; else return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { if (tx_mutex_put(m) == 0) return 0; else return BAD_MUTEX_E; } #elif defined(WOLFSSL_DEOS) int wc_InitMutex(wolfSSL_Mutex* m) { mutexStatus mutStat; /* The empty string "" denotes an anonymous mutex, so objects do not cause name collisions. `protectWolfSSLTemp` in an XML configuration element template describing a mutex. */ if (m) { mutStat = createMutex("", "protectWolfSSLTemp", m); if (mutStat == mutexSuccess) return 0; else{ WOLFSSL_MSG("wc_InitMutex failed"); return mutStat; } } return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { mutexStatus mutStat; if (m) { mutStat = deleteMutex(*m); if (mutStat == mutexSuccess) return 0; else{ WOLFSSL_MSG("wc_FreeMutex failed"); return mutStat; } } return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { mutexStatus mutStat; if (m) { mutStat = lockMutex(*m); if (mutStat == mutexSuccess) return 0; else{ WOLFSSL_MSG("wc_LockMutex failed"); return mutStat; } } return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { mutexStatus mutStat; if (m) { mutStat = unlockMutex(*m); if (mutStat== mutexSuccess) return 0; else{ WOLFSSL_MSG("wc_UnLockMutex failed"); return mutStat; } } return BAD_MUTEX_E; } #elif defined(MICRIUM) #if (OS_VERSION < 50000) #define MICRIUM_ERR_TYPE OS_ERR #define MICRIUM_ERR_NONE OS_ERR_NONE #define MICRIUM_ERR_CODE(err) err #else #define MICRIUM_ERR_TYPE RTOS_ERR #define MICRIUM_ERR_NONE RTOS_ERR_NONE #define MICRIUM_ERR_CODE(err) RTOS_ERR_CODE_GET(err) #endif int wc_InitMutex(wolfSSL_Mutex* m) { MICRIUM_ERR_TYPE err; OSMutexCreate(m, "wolfSSL Mutex", &err); if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE) return 0; else return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED) MICRIUM_ERR_TYPE err; OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err); if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE) return 0; else return BAD_MUTEX_E; #else (void)m; return 0; #endif } int wc_LockMutex(wolfSSL_Mutex* m) { MICRIUM_ERR_TYPE err; OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err); if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { MICRIUM_ERR_TYPE err; OSMutexPost(m, OS_OPT_POST_NONE, &err); if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE) return 0; else return BAD_MUTEX_E; } #elif defined(EBSNET) #if (defined(RTPLATFORM) && (RTPLATFORM != 0)) int wc_InitMutex(wolfSSL_Mutex* m) { if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) return BAD_MUTEX_E; else return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { rtp_sig_mutex_free(*m); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { rtp_sig_mutex_release(*m); return 0; } int ebsnet_fseek(int a, long b, int c) { int retval; retval = vf_lseek(a, b, c); if (retval > 0) retval = 0; else retval = -1; return(retval); } #else static int rtip_semaphore_build(wolfSSL_Mutex *m) { KS_SEMAPHORE_BUILD(m) return(RTP_TRUE); } int wc_InitMutex(wolfSSL_Mutex* m) { if (rtip_semaphore_build(m) == RTP_FALSE) return BAD_MUTEX_E; else return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { KS_SEMAPHORE_FREE(*m); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { if (KS_SEMAPHORE_GET(*m)) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { KS_SEMAPHORE_GIVE(*m); return 0; } #endif int ebsnet_fseek(int a, long b, int c) { int retval; retval = (int)vf_lseek(a, b, c); if (retval > 0) retval = 0; else retval = -1; return(retval); } int strcasecmp(const char *s1, const char *s2) { while (rtp_tolower(*s1) == rtp_tolower(*s2)) { if (*s1 == '\0' || *s2 == '\0') break; s1++; s2++; } return rtp_tolower(*(unsigned char *) s1) - rtp_tolower(*(unsigned char *) s2); } #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) int wc_InitMutex(wolfSSL_Mutex* m) { #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2)) if (wolfCrypt_GetMode_fips() == FIPS_MODE_INIT) return 0; #endif if (_mutex_init(m, NULL) == MQX_EOK) return 0; else return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { if (_mutex_destroy(m) == MQX_EOK) return 0; else return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2)) if (m->VALID != MUTEX_VALID) { if (_mutex_init(m, NULL) != MQX_EOK) return BAD_MUTEX_E; } #endif if (_mutex_lock(m) == MQX_EOK) return 0; else return BAD_MUTEX_E; } int wc_UnLockMutex(wolfSSL_Mutex* m) { #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2)) if (m->VALID != MUTEX_VALID) { if (_mutex_init(m, NULL) != MQX_EOK) return BAD_MUTEX_E; } #endif if (_mutex_unlock(m) == MQX_EOK) return 0; else return BAD_MUTEX_E; } #elif defined(WOLFSSL_TIRTOS) #include int wc_InitMutex(wolfSSL_Mutex* m) { Semaphore_Params params; Error_Block eb; Error_init(&eb); Semaphore_Params_init(¶ms); params.mode = Semaphore_Mode_BINARY; *m = Semaphore_create(1, ¶ms, &eb); if (Error_check(&eb)) { Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.", NULL); return BAD_MUTEX_E; } else return 0; } int wc_FreeMutex(wolfSSL_Mutex* m) { Semaphore_delete(m); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { Semaphore_pend(*m, BIOS_WAIT_FOREVER); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { Semaphore_post(*m); return 0; } #elif defined(WOLFSSL_uITRON4) int wc_InitMutex(wolfSSL_Mutex* m) { int iReturn; m->sem.sematr = TA_TFIFO; m->sem.isemcnt = 1; m->sem.maxsem = 1; m->sem.name = NULL; m->id = acre_sem(&m->sem); if( m->id != E_OK ) iReturn = 0; else iReturn = BAD_MUTEX_E; return iReturn; } int wc_FreeMutex(wolfSSL_Mutex* m) { del_sem( m->id ); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { wai_sem(m->id); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { sig_sem(m->id); return 0; } /**** uITRON malloc/free ***/ static ID ID_wolfssl_MPOOL = 0; static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; int uITRON4_minit(size_t poolsz) { ER ercd; wolfssl_MPOOL.mplsz = poolsz; ercd = acre_mpl(&wolfssl_MPOOL); if (ercd > 0) { ID_wolfssl_MPOOL = ercd; return 0; } else { return -1; } } void *uITRON4_malloc(size_t sz) { ER ercd; void *p = NULL; ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); if (ercd == E_OK) { return p; } else { return 0; } } void *uITRON4_realloc(void *p, size_t sz) { ER ercd; void *newp = NULL; if(p) { ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); if ((ercd == E_OK) && (newp != NULL)) { XMEMCPY(newp, p, sz); ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { return newp; } } } return 0; } void uITRON4_free(void *p) { ER ercd; ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { return; } else { return; } } #elif defined(WOLFSSL_uTKERNEL2) int wc_InitMutex(wolfSSL_Mutex* m) { int iReturn; m->sem.sematr = TA_TFIFO; m->sem.isemcnt = 1; m->sem.maxsem = 1; m->id = tk_cre_sem(&m->sem); if( m->id != NULL ) iReturn = 0; else iReturn = BAD_MUTEX_E; return iReturn; } int wc_FreeMutex(wolfSSL_Mutex* m) { tk_del_sem(m->id); return 0; } int wc_LockMutex(wolfSSL_Mutex* m) { tk_wai_sem(m->id, 1, TMO_FEVR); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { tk_sig_sem(m->id, 1); return 0; } /**** uT-Kernel malloc/free ***/ static ID ID_wolfssl_MPOOL = 0; static T_CMPL wolfssl_MPOOL = { NULL, /* Extended information */ TA_TFIFO, /* Memory pool attribute */ 0, /* Size of whole memory pool (byte) */ "wolfSSL" /* Object name (max 8-char) */ }; int uTKernel_init_mpool(unsigned int sz) { ER ercd; wolfssl_MPOOL.mplsz = sz; ercd = tk_cre_mpl(&wolfssl_MPOOL); if (ercd > 0) { ID_wolfssl_MPOOL = ercd; return 0; } else { return (int)ercd; } } void *uTKernel_malloc(unsigned int sz) { ER ercd; void *p = NULL; ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); if (ercd == E_OK) { return p; } else { return 0; } } void *uTKernel_realloc(void *p, unsigned int sz) { ER ercd; void *newp = NULL; if (p) { ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); if ((ercd == E_OK) && (newp != NULL)) { XMEMCPY(newp, p, sz); ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { return newp; } } } return 0; } void uTKernel_free(void *p) { ER ercd; ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { return; } else { return; } } #elif defined (WOLFSSL_FROSTED) int wc_InitMutex(wolfSSL_Mutex* m) { *m = mutex_init(); if (*m) return 0; else return -1; } int wc_FreeMutex(wolfSSL_Mutex* m) { mutex_destroy(*m); return(0); } int wc_LockMutex(wolfSSL_Mutex* m) { mutex_lock(*m); return 0; } int wc_UnLockMutex(wolfSSL_Mutex* m) { mutex_unlock(*m); return 0; } #elif defined(WOLFSSL_CMSIS_RTOS) #ifndef CMSIS_NMUTEX #define CMSIS_NMUTEX 10 #endif osMutexDef(wolfSSL_mt0); osMutexDef(wolfSSL_mt1); osMutexDef(wolfSSL_mt2); osMutexDef(wolfSSL_mt3); osMutexDef(wolfSSL_mt4); osMutexDef(wolfSSL_mt5); osMutexDef(wolfSSL_mt6); osMutexDef(wolfSSL_mt7); osMutexDef(wolfSSL_mt8); osMutexDef(wolfSSL_mt9); static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0), osMutex(wolfSSL_mt1), osMutex(wolfSSL_mt2), osMutex(wolfSSL_mt3), osMutex(wolfSSL_mt4), osMutex(wolfSSL_mt5), osMutex(wolfSSL_mt6), osMutex(wolfSSL_mt7), osMutex(wolfSSL_mt8), osMutex(wolfSSL_mt9) }; static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0}; int wc_InitMutex(wolfSSL_Mutex* m) { int i; if(!osKernelRunning()) { return 0; } for (i=0; imutex, "wolfSSL Lock", TX_INHERIT) == TX_SUCCESS) return 0; else return BAD_MUTEX_E; } int wc_FreeMutex(wolfSSL_Mutex* m) { if (tx_mutex_delete(&ready->mutex) == TX_SUCCESS) return 0; else return BAD_MUTEX_E; } int wc_LockMutex(wolfSSL_Mutex* m) { } int wc_UnLockMutex(wolfSSL_Mutex* m) { } #elif defined(WOLFSSL_USER_MUTEX) /* Use user own mutex */ /* int wc_InitMutex(wolfSSL_Mutex* m) { ... } int wc_FreeMutex(wolfSSL_Mutex *m) { ... } int wc_LockMutex(wolfSSL_Mutex *m) { ... } int wc_UnLockMutex(wolfSSL_Mutex *m) { ... } */ #else #warning No mutex handling defined #endif #if !defined(WOLFSSL_USE_RWLOCK) || defined(SINGLE_THREADED) || \ (defined(WC_MUTEX_OPS_INLINE) && !defined(WC_RWLOCK_OPS_INLINE)) int wc_InitRwLock(wolfSSL_RwLock* m) { return wc_InitMutex(m); } int wc_FreeRwLock(wolfSSL_RwLock* m) { return wc_FreeMutex(m); } int wc_LockRwLock_Wr(wolfSSL_RwLock* m) { return wc_LockMutex(m); } int wc_LockRwLock_Rd(wolfSSL_RwLock* m) { return wc_LockMutex(m); } int wc_UnLockRwLock(wolfSSL_RwLock* m) { return wc_UnLockMutex(m); } #endif #ifndef NO_ASN_TIME #if defined(_WIN32_WCE) time_t windows_time(time_t* timer) { SYSTEMTIME sysTime; FILETIME fTime; ULARGE_INTEGER intTime; GetSystemTime(&sysTime); SystemTimeToFileTime(&sysTime, &fTime); XMEMCPY(&intTime, &fTime, sizeof(FILETIME)); /* subtract EPOCH */ intTime.QuadPart -= 0x19db1ded53e8000; /* to secs */ intTime.QuadPart /= 10000000; if (timer != NULL) *timer = (time_t)intTime.QuadPart; return (time_t)intTime.QuadPart; } #endif /* _WIN32_WCE */ #if defined(WOLFSSL_APACHE_MYNEWT) #include "os/os_time.h" time_t mynewt_time(time_t* timer) { time_t now; struct os_timeval tv; os_gettimeofday(&tv, NULL); now = (time_t)tv.tv_sec; if(timer != NULL) { *timer = now; } return now; } #endif /* WOLFSSL_APACHE_MYNEWT */ #if defined(WOLFSSL_GMTIME) struct tm* gmtime_r(const time_t* timer, struct tm *ret) { #define YEAR0 1900 #define EPOCH_YEAR 1970 #define SECS_DAY (24L * 60L * 60L) #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400))) #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) static const int _ytab[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; time_t secs = *timer; unsigned long dayclock, dayno; int year = EPOCH_YEAR; dayclock = (unsigned long)secs % SECS_DAY; dayno = (unsigned long)secs / SECS_DAY; ret->tm_sec = (int) dayclock % 60; ret->tm_min = (int)(dayclock % 3600) / 60; ret->tm_hour = (int) dayclock / 3600; ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */ while(dayno >= (unsigned long)YEARSIZE(year)) { dayno -= YEARSIZE(year); year++; } ret->tm_year = year - YEAR0; ret->tm_yday = (int)dayno; ret->tm_mon = 0; while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) { dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon]; ret->tm_mon++; } ret->tm_mday = (int)++dayno; #ifndef WOLFSSL_LINUXKM ret->tm_isdst = 0; #endif return ret; } struct tm* gmtime(const time_t* timer) { static struct tm st_time; return gmtime_r(timer, &st_time); } #endif /* WOLFSSL_GMTIME */ #if defined(HAVE_RTP_SYS) #define YEAR0 1900 struct tm* rtpsys_gmtime(const time_t* timer) /* has a gmtime() but hangs */ { static struct tm st_time; struct tm* ret = &st_time; DC_RTC_CALENDAR cal; dc_rtc_time_get(&cal, TRUE); ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */ ret->tm_mon = cal.month - 1; /* gm starts at 0 */ ret->tm_mday = cal.day; ret->tm_hour = cal.hour; ret->tm_min = cal.minute; ret->tm_sec = cal.second; return ret; } #endif /* HAVE_RTP_SYS */ #if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) /* * time() is just a stub in Microchip libraries. We need our own * implementation. Use SNTP client to get seconds since epoch. */ time_t pic32_time(time_t* timer) { #ifdef MICROCHIP_TCPIP_V5 DWORD sec = 0; #else word32 sec = 0; #endif #ifdef MICROCHIP_MPLAB_HARMONY sec = TCPIP_SNTP_UTCSecondsGet(); #else sec = SNTPGetUTCSeconds(); #endif if (timer != NULL) *timer = (time_t)sec; return (time_t)sec; } #endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ #if defined(WOLFSSL_DEOS) || defined(WOLFSSL_DEOS_RTEMS) time_t deos_time(time_t* timer) { const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); const volatile word32 *systemTickPtr = systemTickPointer(); if (timer != NULL) *timer = *systemTickPtr/systemTickTimeInHz; #if defined(CURRENT_UNIX_TIMESTAMP) /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */ return (time_t) (*systemTickPtr/systemTickTimeInHz) + CURRENT_UNIX_TIMESTAMP; #else return (time_t) *systemTickPtr/systemTickTimeInHz; #endif } #endif /* WOLFSSL_DEOS || WOLFSSL_DEOS_RTEMS */ #if defined(FREESCALE_RTC) #include "fsl_rtc.h" time_t fsl_time(time_t* t) { *t = RTC_GetSecondsTimerCount(RTC); return *t; } #endif #if defined(FREESCALE_SNVS_RTC) time_t fsl_time(time_t* t) { struct tm tm_time; time_t ret; snvs_hp_rtc_datetime_t rtcDate; snvs_hp_rtc_config_t snvsRtcConfig; SNVS_HP_RTC_GetDefaultConfig(&snvsRtcConfig); SNVS_HP_RTC_Init(SNVS, &snvsRtcConfig); SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate); tm_time.tm_year = rtcDate.year; tm_time.tm_mon = rtcDate.month; tm_time.tm_mday = rtcDate.day; tm_time.tm_hour = rtcDate.hour; tm_time.tm_min = rtcDate.minute; tm_time.tm_sec = rtcDate.second; ret = mktime(&tm_time); if (t != NULL) *t = ret; return ret; } #endif #if defined(MICRIUM) time_t micrium_time(time_t* timer) { CLK_TS_SEC sec; Clk_GetTS_Unix(&sec); if (timer != NULL) *timer = sec; return (time_t) sec; } #endif /* MICRIUM */ #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) time_t mqx_time(time_t* timer) { TIME_STRUCT time_s; _time_get(&time_s); if (timer != NULL) *timer = (time_t)time_s.SECONDS; return (time_t)time_s.SECONDS; } #endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ #if defined(MAX3266X_RTC) #define XTIME wc_MXC_RTC_Time #endif #if defined(WOLFSSL_TIRTOS) && defined(USER_TIME) time_t XTIME(time_t * timer) { time_t sec = 0; sec = (time_t) Seconds_get(); if (timer != NULL) *timer = sec; return sec; } #endif /* WOLFSSL_TIRTOS */ #if defined(WOLFSSL_XILINX) #include "xrtcpsu.h" time_t xilinx_time(time_t * timer) { time_t sec = 0; XRtcPsu_Config* con; XRtcPsu rtc; con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID); if (con != NULL) { if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) { sec = (time_t)XRtcPsu_GetCurrentTime(&rtc); } else { WOLFSSL_MSG("Unable to initialize RTC"); } } if (timer != NULL) *timer = sec; return sec; } #endif /* WOLFSSL_XILINX */ #if defined(WOLFSSL_ZEPHYR) time_t z_time(time_t * timer) { struct timespec ts; #if defined(CONFIG_RTC) && \ (defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC)) #if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM) /* When using native sim, get time from simulator rtc */ uint32_t nsec = 0; uint64_t sec = 0; native_rtc_gettime(RTC_CLOCK_PSEUDOHOSTREALTIME, &nsec, &sec); if (timer != NULL) *timer = sec; return sec; #else /* Try to obtain the actual time from an RTC */ static const struct device *rtc = DEVICE_DT_GET(DT_NODELABEL(rtc)); if (device_is_ready(rtc)) { struct rtc_time rtc_time; struct tm *tm_time = rtc_time_to_tm(&rtc_time); int ret = rtc_get_time(rtc, &rtc_time); if (ret == 0) { time_t epochTime = mktime(tm_time); if (timer != NULL) *timer = epochTime; return epochTime; } } #endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */ #endif /* Fallback to uptime since boot. This works for relative times, but * not for ASN.1 date validation */ if (clock_gettime(CLOCK_REALTIME, &ts) == 0) if (timer != NULL) *timer = ts.tv_sec; return ts.tv_sec; } #endif /* WOLFSSL_ZEPHYR */ #if defined(WOLFSSL_WICED) #ifndef WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME #error Please define WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME at build time. #endif /* WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME */ time_t wiced_pseudo_unix_epoch_time(time_t * timer) { time_t epoch_time; /* The time() function return uptime on WICED platform. */ epoch_time = time(NULL) + WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME; if (timer != NULL) { *timer = epoch_time; } return epoch_time; } #endif /* WOLFSSL_WICED */ #ifdef WOLFSSL_TELIT_M2MB time_t m2mb_xtime(time_t * timer) { time_t myTime = 0; INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); if (fd != -1) { M2MB_RTC_TIMEVAL_T timeval; m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); myTime = timeval.sec; m2mb_rtc_close(fd); } return myTime; } #ifdef WOLFSSL_TLS13 time_t m2mb_xtime_ms(time_t * timer) { time_t myTime = 0; INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); if (fd != -1) { M2MB_RTC_TIMEVAL_T timeval; m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); myTime = timeval.sec + timeval.msec; m2mb_rtc_close(fd); } return myTime; } #endif /* WOLFSSL_TLS13 */ #ifndef NO_CRYPT_BENCHMARK double m2mb_xtime_bench(int reset) { double myTime = 0; INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); if (fd != -1) { M2MB_RTC_TIMEVAL_T timeval; m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); myTime = (double)timeval.sec + ((double)timeval.msec / 1000); m2mb_rtc_close(fd); } return myTime; } #endif /* !NO_CRYPT_BENCHMARK */ #endif /* WOLFSSL_TELIT_M2MB */ #if defined(WOLFSSL_LINUXKM) time_t time(time_t * timer) { time_t ret; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) struct timespec ts; getnstimeofday(&ts); ret = ts.tv_sec; #else struct timespec64 ts; #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) ts = current_kernel_time64(); #else ktime_get_coarse_real_ts64(&ts); #endif ret = ts.tv_sec; #endif if (timer) *timer = ret; return ret; } #endif /* WOLFSSL_LINUXKM */ #ifdef HAL_RTC_MODULE_ENABLED extern RTC_HandleTypeDef hrtc; time_t stm32_hal_time(time_t *t1) { struct tm tm_time; time_t ret; RTC_TimeTypeDef time; RTC_DateTypeDef date; XMEMSET(&tm_time, 0, sizeof(struct tm)); /* order of GetTime followed by GetDate required here due to STM32 HW * requirement */ HAL_RTC_GetTime(&hrtc, &time, FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &date, FORMAT_BIN); /* RTC year is 0-99 and "struct tm" is 1900+, so assume after year 2000 */ tm_time.tm_year = date.Year + 100; /* RTC month is 1-12 and "struct tm" is 0-12, so subtract 1 */ tm_time.tm_mon = date.Month - 1; tm_time.tm_mday = date.Date; tm_time.tm_hour = time.Hours; tm_time.tm_min = time.Minutes; tm_time.tm_sec = time.Seconds; ret = mktime(&tm_time); if (t1 != NULL) *t1 = ret; return ret; } #endif /* HAL_RTC_MODULE_ENABLED */ #endif /* !NO_ASN_TIME */ #if (!defined(WOLFSSL_LEANPSK) && !defined(STRING_USER)) || \ defined(USE_WOLF_STRNSTR) char* wolfSSL_strnstr(const char* s1, const char* s2, size_t n) { size_t s2_len = XSTRLEN(s2); if (s2_len == 0) return (char *)(wc_ptr_t)s1; while (n >= s2_len && s1[0]) { if (s1[0] == s2[0]) if (XMEMCMP(s1, s2, s2_len) == 0) return (char *)(wc_ptr_t)s1; s1++; n--; } return NULL; } #endif /* custom memory wrappers */ #ifdef WOLFSSL_NUCLEUS_1_2 /* system memory pool */ extern NU_MEMORY_POOL System_Memory; void* nucleus_malloc(unsigned long size, void* heap, int type) { STATUS status; void* stack_ptr; status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size, NU_NO_SUSPEND); if (status == NU_SUCCESS) { return 0; } else { return stack_ptr; } } void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type) { DM_HEADER* old_header; word32 old_size, copy_size; void* new_mem; /* if ptr is NULL, behave like malloc */ new_mem = nucleus_malloc(size, NULL, 0); if (new_mem == 0 || ptr == 0) { return new_mem; } /* calculate old memory block size */ /* mem pointers stored in block headers (ref dm_defs.h) */ old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD); old_size = (byte*)old_header->dm_next_memory - (byte*)ptr; /* copy old to new */ if (old_size < size) { copy_size = old_size; } else { copy_size = size; } XMEMCPY(new_mem, ptr, copy_size); /* free old */ nucleus_free(ptr, NULL, 0); return new_mem; } void nucleus_free(void* ptr, void* heap, int type) { if (ptr != NULL) NU_Deallocate_Memory(ptr); } #endif /* WOLFSSL_NUCLEUS_1_2 */ #if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) #include /* initialize and Mutex for TI Crypt Engine */ #include /* md5, sha1, sha224, sha256 */ #endif #if defined(WOLFSSL_CRYPTOCELL) #define WOLFSSL_CRYPTOCELL_C #include /* CC310, RTC and RNG */ #if !defined(NO_SHA256) #define WOLFSSL_CRYPTOCELL_HASH_C #include /* sha256 */ #endif #endif #ifndef SINGLE_THREADED /* Environment-specific multi-thread implementation check */ #if defined(__WATCOMC__) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { if (thread == NULL || cb == NULL) return BAD_FUNC_ARG; #if defined(__OS2__) *thread = _beginthread(cb, NULL, 0, arg); if (*thread == INVALID_THREAD_VAL) { return MEMORY_E; } #elif defined(__NT__) /* Use _beginthreadex instead of _beginthread because of: * _beginthreadex is safer to use than _beginthread. If the thread * that's generated by _beginthread exits quickly, the handle that's * returned to the caller of _beginthread might be invalid or point * to another thread. However, the handle that's returned by * _beginthreadex has to be closed by the caller of _beginthreadex, * so it's guaranteed to be a valid handle if _beginthreadex didn't * return an error.*/ *thread = _beginthreadex(NULL, 0, cb, arg, 0, NULL); if (*thread == 0) { *thread = INVALID_THREAD_VAL; return MEMORY_E; } #elif defined(__LINUX__) if (pthread_create(thread, NULL, cb, arg)) return MEMORY_E; #endif return 0; } int wolfSSL_JoinThread(THREAD_TYPE thread) { int ret = 0; if (thread == INVALID_THREAD_VAL) return BAD_FUNC_ARG; #if defined(__OS2__) DosWaitThread(&thread, DCWW_WAIT); #elif defined(__NT__) /* We still want to attempt to close the thread handle even on error */ if (WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_FAILED) ret = MEMORY_E; if (CloseHandle((HANDLE)thread) == 0) ret = MEMORY_E; #elif defined(__LINUX__) if (pthread_join(thread, NULL) != 0) ret = MEMORY_E; #endif return ret; } #if defined(WOLFSSL_THREAD_NO_JOIN) int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg) { THREAD_TYPE thread; int ret = 0; if (cb == NULL) return BAD_FUNC_ARG; #if defined(__OS2__) thread = _beginthread(cb, NULL, 0, arg); if (thread == INVALID_THREAD_VAL) ret = MEMORY_E; #elif defined(__NT__) thread = _beginthread(cb, 0, arg); if (thread == -1L) ret = MEMORY_E; #elif defined(__LINUX__) XMEMSET(&thread, 0, sizeof(thread)); ret = wolfSSL_NewThread(&thread, cb, arg); if (ret == 0) ret = pthread_detach(thread); #endif return ret; } #endif #ifdef WOLFSSL_COND int wolfSSL_CondInit(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__MACH__) cond->cond = dispatch_semaphore_create(0); if (cond->cond == NULL) return MEMORY_E; /* dispatch_release() fails hard, with Trace/BPT trap signal, if the * sem's internal count is less than the value passed in with * dispatch_semaphore_create(). work around this by initializing * with 0, then incrementing it afterwards. */ if (dispatch_semaphore_signal(s->sem) < 0) { dispatch_release(s->sem); return MEMORY_E; } #elif defined(__OS2__) DosCreateMutexSem( NULL, &cond->mutex, 0, FALSE ); DosCreateEventSem( NULL, &cond->cond, DCE_POSTONE, FALSE ); #elif defined(__NT__) cond->cond = CreateEventA(NULL, FALSE, FALSE, NULL); if (cond->cond == NULL) return MEMORY_E; if (wc_InitMutex(&cond->mutex) != 0) { if (CloseHandle(cond->cond) == 0) return MEMORY_E; return MEMORY_E; } #elif defined(__LINUX__) if (pthread_mutex_init(&cond->mutex, NULL) != 0) return MEMORY_E; if (pthread_cond_init(&cond->cond, NULL) != 0) { /* Keep compilers happy that we are using the return code */ if (pthread_mutex_destroy(&cond->mutex) != 0) return MEMORY_E; return MEMORY_E; } #endif return 0; } int wolfSSL_CondFree(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__MACH__) dispatch_release(cond->cond); #elif defined(__OS2__) DosCloseMutexSem(cond->mutex); DosCloseEventSem(cond->cond); #elif defined(__NT__) if (CloseHandle(cond->cond) == 0) return MEMORY_E; #elif defined(__LINUX__) if (pthread_mutex_destroy(&cond->mutex) != 0) return MEMORY_E; if (pthread_cond_destroy(&cond->cond) != 0) return MEMORY_E; #endif return 0; } int wolfSSL_CondStart(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__MACH__) #elif defined(__OS2__) #elif defined(__NT__) if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; #elif defined(__LINUX__) if (pthread_mutex_lock(&cond->mutex) != 0) return BAD_MUTEX_E; #endif return 0; } int wolfSSL_CondSignal(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__MACH__) dispatch_semaphore_signal(cond->cond); #elif defined(__OS2__) #elif defined(__NT__) if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; if (SetEvent(cond->cond) == 0) return MEMORY_E; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; #elif defined(__LINUX__) if (pthread_cond_signal(&cond->cond) != 0) return MEMORY_E; #endif return 0; } int wolfSSL_CondWait(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__MACH__) dispatch_semaphore_wait(cond->cond, DISPATCH_TIME_FOREVER); #elif defined(__OS2__) #elif defined(__NT__) if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; if (WaitForSingleObject(cond->cond, INFINITE) == WAIT_FAILED) return MEMORY_E; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; #elif defined(__LINUX__) if (pthread_cond_wait(&cond->cond, &cond->mutex) != 0) return MEMORY_E; #endif return 0; } int wolfSSL_CondEnd(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; #if defined(__OS2__) #elif defined(__NT__) if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; #elif defined(__LINUX__) if (pthread_mutex_unlock(&cond->mutex) != 0) return BAD_MUTEX_E; #endif return 0; } #endif /* WOLFSSL_COND */ #elif defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS) && \ !defined(_WIN32_WCE) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { if (thread == NULL || cb == NULL) return BAD_FUNC_ARG; /* Use _beginthreadex instead of _beginthread because of: * _beginthreadex is safer to use than _beginthread. If the thread * that's generated by _beginthread exits quickly, the handle that's * returned to the caller of _beginthread might be invalid or point * to another thread. However, the handle that's returned by * _beginthreadex has to be closed by the caller of _beginthreadex, * so it's guaranteed to be a valid handle if _beginthreadex didn't * return an error.*/ *thread = _beginthreadex(NULL, 0, cb, arg, 0, NULL); if (*thread == 0) { *thread = INVALID_THREAD_VAL; return MEMORY_E; } return 0; } #ifdef WOLFSSL_THREAD_NO_JOIN int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg) { THREAD_TYPE thread; if (cb == NULL) return BAD_FUNC_ARG; thread = _beginthread(cb, 0, arg); if (thread == -1L) { return MEMORY_E; } return 0; } #endif int wolfSSL_JoinThread(THREAD_TYPE thread) { int ret = 0; if (thread == INVALID_THREAD_VAL) return BAD_FUNC_ARG; /* We still want to attempt to close the thread handle even on error */ if (WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_FAILED) ret = MEMORY_E; if (CloseHandle((HANDLE)thread) == 0) ret = MEMORY_E; return ret; } #ifdef WOLFSSL_COND int wolfSSL_CondInit(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; cond->cond = CreateEventA(NULL, FALSE, FALSE, NULL); if (cond->cond == NULL) return MEMORY_E; if (wc_InitMutex(&cond->mutex) != 0) { if (CloseHandle(cond->cond) == 0) return MEMORY_E; return MEMORY_E; } return 0; } int wolfSSL_CondFree(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (CloseHandle(cond->cond) == 0) return MEMORY_E; return 0; } int wolfSSL_CondStart(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondSignal(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; if (SetEvent(cond->cond) == 0) return MEMORY_E; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondWait(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; if (WaitForSingleObject(cond->cond, INFINITE) == WAIT_FAILED) return MEMORY_E; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondEnd(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } #endif /* WOLFSSL_COND */ #elif defined(WOLFSSL_TIRTOS) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { /* Initialize the defaults and set the parameters. */ Task_Params taskParams; Task_Params_init(&taskParams); taskParams.arg0 = (UArg)arg; taskParams.stackSize = 65535; *thread = Task_create((Task_FuncPtr)cb, &taskParams, NULL); if (*thread == NULL) { return MEMORY_E; } Task_yield(); return 0; } int wolfSSL_JoinThread(THREAD_TYPE thread) { while(1) { if (Task_getMode(thread) == Task_Mode_TERMINATED) { Task_sleep(5); break; } Task_yield(); } return 0; } #elif defined(NETOS) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { /* For backwards compatibility allow using this declaration as well. */ #ifdef TESTSUITE_THREAD_STACK_SZ #define WOLFSSL_NETOS_STACK_SZ TESTSUITE_THREAD_STACK_SZ #endif /* This can be adjusted by defining in user_settings.h, will default to * 65k in the event it is undefined */ #ifndef WOLFSSL_NETOS_STACK_SZ #define WOLFSSL_NETOS_STACK_SZ 65535 #endif int result; if (thread == NULL || cb == NULL) return BAD_FUNC_ARG; XMEMSET(thread, 0, sizeof(*thread)); thread->threadStack = (void *)XMALLOC(WOLFSSL_NETOS_STACK_SZ, NULL, DYNAMIC_TYPE_OS_BUF); if (thread->threadStack == NULL) return MEMORY_E; /* first create the idle thread: * ARGS: * Param1: pointer to thread * Param2: name * Param3 and 4: entry function and input * Param5: pointer to thread stack * Param6: stack size * Param7 and 8: priority level and preempt threshold * Param9 and 10: time slice and auto-start indicator */ result = tx_thread_create(&thread->tid, "wolfSSL thread", (entry_functionType)cb, (ULONG)arg, thread->threadStack, WOLFSSL_NETOS_STACK_SZ, 2, 2, 1, TX_AUTO_START); if (result != TX_SUCCESS) { XFREE(thread->threadStack, NULL, DYNAMIC_TYPE_OS_BUF); thread->threadStack = NULL; return MEMORY_E; } return 0; } int wolfSSL_JoinThread(THREAD_TYPE thread) { /* TODO: maybe have to use tx_thread_delete? */ XFREE(thread.threadStack, NULL, DYNAMIC_TYPE_OS_BUF); thread.threadStack = NULL; return 0; } #elif defined(WOLFSSL_ZEPHYR) void* wolfsslThreadHeapHint = NULL; int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { #ifndef WOLFSSL_ZEPHYR_STACK_SZ #define WOLFSSL_ZEPHYR_STACK_SZ (48*1024) #endif if (thread == NULL || cb == NULL) return BAD_FUNC_ARG; XMEMSET(thread, 0, sizeof(*thread)); thread->tid = (struct k_thread*)XMALLOC( Z_KERNEL_STACK_SIZE_ADJUST(sizeof(struct k_thread)), wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); if (thread->tid == NULL) { WOLFSSL_MSG("error: XMALLOC thread->tid failed"); return MEMORY_E; } /* TODO: Use the following once k_thread_stack_alloc makes it into a * release. * thread->threadStack = k_thread_stack_alloc(WOLFSSL_ZEPHYR_STACK_SZ, * 0); */ thread->threadStack = (void*)XMALLOC( Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ), wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); if (thread->threadStack == NULL) { XFREE(thread->tid, wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); thread->tid = NULL; WOLFSSL_MSG("error: XMALLOC thread->threadStack failed"); return MEMORY_E; } /* k_thread_create does not return any error codes */ /* Casting to k_thread_entry_t should be fine since we just ignore the * extra arguments being passed in */ k_thread_create(thread->tid, thread->threadStack, WOLFSSL_ZEPHYR_STACK_SZ, (k_thread_entry_t)cb, arg, NULL, NULL, 5, 0, K_NO_WAIT); return 0; } int wolfSSL_JoinThread(THREAD_TYPE thread) { int ret = 0; int err; err = k_thread_join(thread.tid, K_FOREVER); if (err != 0) ret = MEMORY_E; XFREE(thread.tid, wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); thread.tid = NULL; /* TODO: Use the following once k_thread_stack_free makes it into a * release. * err = k_thread_stack_free(thread.threadStack); * if (err != 0) * ret = MEMORY_E; */ XFREE(thread.threadStack, wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); thread.threadStack = NULL; /* No thread resources to free. Everything is stored in thread.tid */ return ret; } #ifdef WOLFSSL_COND /* Use the pthreads translation layer for signaling */ #endif /* WOLFSSL_COND */ #elif defined(WOLFSSL_PTHREADS) || \ (defined(FREERTOS) && defined(WOLFSSL_ESPIDF)) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { if (thread == NULL || cb == NULL) return BAD_FUNC_ARG; if (pthread_create(thread, NULL, cb, arg) != 0) return MEMORY_E; return 0; } #ifdef WOLFSSL_THREAD_NO_JOIN int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg) { THREAD_TYPE thread; int ret; XMEMSET(&thread, 0, sizeof(thread)); ret = wolfSSL_NewThread(&thread, cb, arg); if (ret == 0) ret = pthread_detach(thread); return ret; } #endif int wolfSSL_JoinThread(THREAD_TYPE thread) { if (thread == INVALID_THREAD_VAL) return BAD_FUNC_ARG; if (pthread_join(thread, NULL) != 0) return MEMORY_E; return 0; } #ifdef WOLFSSL_COND #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 \ && !defined(__ppc__) /* Apple style dispatch semaphore */ int wolfSSL_CondInit(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; /* dispatch_release() fails hard, with Trace/BPT trap signal, if the * sem's internal count is less than the value passed in with * dispatch_semaphore_create(). work around this by initing * with 0, then incrementing it afterwards. */ cond->cond = dispatch_semaphore_create(0); if (cond->cond == NULL) return MEMORY_E; if (wc_InitMutex(&cond->mutex) != 0) { dispatch_release(cond->cond); return MEMORY_E; } return 0; } int wolfSSL_CondFree(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; dispatch_release(cond->cond); cond->cond = NULL; if (wc_FreeMutex(&cond->mutex) != 0) { return MEMORY_E; } return 0; } int wolfSSL_CondStart(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondSignal(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; dispatch_semaphore_signal(cond->cond); if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondWait(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; dispatch_semaphore_wait(cond->cond, DISPATCH_TIME_FOREVER); if (wc_LockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondEnd(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (wc_UnLockMutex(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } #else /* Generic POSIX conditional */ int wolfSSL_CondInit(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (pthread_mutex_init(&cond->mutex, NULL) != 0) return MEMORY_E; if (pthread_cond_init(&cond->cond, NULL) != 0) { /* Keep compilers happy that we are using the return code */ if (pthread_mutex_destroy(&cond->mutex) != 0) return MEMORY_E; return MEMORY_E; } return 0; } int wolfSSL_CondFree(COND_TYPE* cond) { int ret = 0; if (cond == NULL) return BAD_FUNC_ARG; if (pthread_mutex_destroy(&cond->mutex) != 0) ret = MEMORY_E; if (pthread_cond_destroy(&cond->cond) != 0) ret = MEMORY_E; return ret; } int wolfSSL_CondStart(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (pthread_mutex_lock(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } int wolfSSL_CondSignal(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (pthread_cond_signal(&cond->cond) != 0) return MEMORY_E; return 0; } int wolfSSL_CondWait(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (pthread_cond_wait(&cond->cond, &cond->mutex) != 0) return MEMORY_E; return 0; } int wolfSSL_CondEnd(COND_TYPE* cond) { if (cond == NULL) return BAD_FUNC_ARG; if (pthread_mutex_unlock(&cond->mutex) != 0) return BAD_MUTEX_E; return 0; } #endif /* __MACH__ */ #endif /* WOLFSSL_COND */ #endif /* Environment check */ #endif /* not SINGLE_THREADED */ #if (defined(__unix__) || defined(__APPLE__)) && \ !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) #include #include #include #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC 0 #endif void wc_set_cloexec(int fd) { #ifdef FD_CLOEXEC int fdFlags; if (fd < 0) return; fdFlags = fcntl(fd, F_GETFD); if (fdFlags >= 0) (void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC); #else (void)fd; #endif } int wc_open_cloexec(const char* path, int flags) { int fd = open(path, flags | O_CLOEXEC); #ifdef FD_CLOEXEC if (fd < 0 && errno == EINVAL) { fd = open(path, flags); wc_set_cloexec(fd); } #endif return fd; } int wc_socket_cloexec(int domain, int type, int protocol) { int fd = socket(domain, type | SOCK_CLOEXEC, protocol); #ifdef FD_CLOEXEC if (fd < 0 && errno == EINVAL) { fd = socket(domain, type, protocol); wc_set_cloexec(fd); } #endif return fd; } int wc_accept_cloexec(int sockfd, void* addr, void* addrlen) { int fd; #if (defined(__USE_GNU) && (defined(__linux__) || defined(__ANDROID__))) || \ (defined(__FreeBSD__) && defined(__BSD_VISIBLE) && __BSD_VISIBLE && \ (__FreeBSD_version >= 1000000)) fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen, SOCK_CLOEXEC); if (fd >= 0) return fd; if (errno != ENOSYS && errno != EINVAL) return fd; #endif fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen); wc_set_cloexec(fd); return fd; } #endif /* (__unix__ || __APPLE__) && !WOLFSSL_LINUXKM && !WOLFSSL_ZEPHYR */ #if defined(WOLFSSL_LINUXKM) && defined(CONFIG_ARM64) && \ defined(WC_SYM_RELOC_TABLES) #ifndef CONFIG_ARCH_TEGRA #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) noinstr void my__alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr, __le32 *updptr, int nr_inst) { return WC_PIE_INDIRECT_SYM(alt_cb_patch_nops) (alt, origptr, updptr, nr_inst); } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) */ void my__queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) { return WC_PIE_INDIRECT_SYM(queued_spin_lock_slowpath) (lock, val); } #endif #endif