Coverage Report

Created: 2026-11-12 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/wolfcrypt/src/wc_port.c
Line
Count
Source
1
/* port.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#if (defined(__linux__) || defined(__ANDROID__)) && \
23
    !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) && \
24
    !defined(_GNU_SOURCE)
25
    #define _GNU_SOURCE 1
26
#elif defined(__FreeBSD__)
27
    /* for __FreeBSD_version */
28
    #include <sys/param.h>
29
#elif (defined(__CYGWIN__) || defined(__MSYS__)) && !defined(_GNU_SOURCE)
30
    /* dladdr and Dl_info, for the RNG fork handler pin, hide behind it */
31
    #define _GNU_SOURCE 1
32
#endif
33
34
/*
35
wolfCrypt Porting Build Options:
36
37
Threading/Mutex options:
38
 * SINGLE_THREADED:     No-op mutex/threading implementations   default: off
39
 * WOLFSSL_PTHREADS:    Use pthread-based mutex/threading       default: off
40
 *                      (auto-detected on most POSIX systems)
41
 * WOLFSSL_MUTEX_INITIALIZER: Use static mutex initialization   default: off
42
 * WC_MUTEX_OPS_INLINE: Use inlined mutex operations            default: off
43
 * WOLFSSL_USER_MUTEX:  User-provided mutex implementation      default: off
44
 * WOLFSSL_COND:        Enable condition variable support       default: off
45
 * WOLFSSL_USE_RWLOCK:  Enable reader-writer lock support       default: off
46
 * WOLFSSL_THREAD_NO_JOIN: Create threads without join          default: off
47
 * WOLFSSL_ALGO_HW_MUTEX: Per-algorithm hardware mutex locks    default: off
48
 *                      Controls AES, hash, PK, and RNG mutexes.
49
 * WOLFSSL_CRYPT_HW_MUTEX: Cryptography hardware mutex          default: off
50
 *                      Master control for all HW mutex init.
51
 * NO_AES_MUTEX:        Disable AES hardware mutex              default: off
52
 * NO_HASH_MUTEX:       Disable hash hardware mutex             default: off
53
 * NO_PK_MUTEX:         Disable public-key hardware mutex       default: off
54
 * NO_RNG_MUTEX:        Disable RNG hardware mutex              default: off
55
 *
56
 * Memory options:
57
 * USE_WOLFSSL_MEMORY:  Enable custom memory allocation hooks   default: on
58
 * WOLFSSL_STATIC_MEMORY: Use static memory pools instead of    default: off
59
 *                      dynamic allocation.
60
 * WOLFSSL_TRACK_MEMORY: Enable memory allocation tracking      default: off
61
 * WOLFSSL_TRACK_MEMORY_VERBOSE: Verbose memory tracking output default: off
62
 * WOLFSSL_FORCE_MALLOC_FAIL_TEST: Force malloc failures for    default: off
63
 *                      testing error handling paths.
64
 * WOLFSSL_MEM_FAIL_COUNT: Count malloc failures for testing    default: off
65
 * WOLFSSL_CHECK_MEM_ZERO: Verify sensitive memory is zeroed    default: off
66
 *                      on free. Debug tool for key material.
67
 *
68
 * Filesystem options:
69
 * NO_FILESYSTEM:       Disable all filesystem operations       default: off
70
 * NO_WOLFSSL_DIR:      Disable directory listing/iteration     default: off
71
 *
72
 * Time options:
73
 * WOLFSSL_GMTIME:      Provide custom gmtime implementation    default: off
74
 * HAVE_TIME_T_TYPE:    Platform provides time_t                default: auto
75
 * TIME_OVERRIDES:      Application provides custom time funcs  default: off
76
 * USER_TICKS:          Application provides tick counter       default: off
77
 * USE_WOLF_TM:         Use wolfSSL struct tm definition        default: off
78
 *
79
 * String function options:
80
 * STRING_USER:         User provides all string functions      default: off
81
 * USE_WOLF_STRTOK:     Use wolfSSL strtok implementation       default: off
82
 * USE_WOLF_STRSEP:     Use wolfSSL strsep implementation       default: off
83
 * USE_WOLF_STRLCPY:    Use wolfSSL strlcpy implementation      default: off
84
 * USE_WOLF_STRLCAT:    Use wolfSSL strlcat implementation      default: off
85
 * USE_WOLF_STRCASECMP: Use wolfSSL strcasecmp implementation   default: off
86
 * USE_WOLF_STRNCASECMP:Use wolfSSL strncasecmp implementation  default: off
87
 * USE_WOLF_STRDUP:     Use wolfSSL strdup implementation       default: off
88
 *
89
 * Atomic operation options:
90
 * WOLFSSL_ATOMIC_OPS:  Enable atomic operations for thread     default: off
91
 *                      safety without full mutexes.
92
 * WOLFSSL_USER_DEFINED_ATOMICS: User-provided atomic impl     default: off
93
 * WOLFSSL_HAVE_ATOMIC_H: Has C11 atomic.h header              default: off
94
 *
95
 * Socket options:
96
 * HAVE_ACCEPT4:        Use accept4() for close-on-exec accept  default: auto
97
 *                      (configure/CMake detect it; set it for
98
 *                      musl or another unrecognised libc)
99
 *
100
 * General options:
101
 * WOLFCRYPT_ONLY:      Exclude TLS/SSL, wolfCrypt only build   default: off
102
 * WOLFSSL_LEANPSK:     Lean PSK build, minimal features        default: off
103
 * WOLF_C89:            C89 compatibility mode                  default: off
104
 * WOLFSSL_SMALL_STACK: Reduce stack usage by allocating from   default: off
105
 *                      heap instead. Slower but needed for
106
 *                      constrained environments.
107
 * DEBUG_WOLFSSL_VERBOSE: Enable verbose debug logging           default: off
108
 */
109
110
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
111
112
#ifdef __APPLE__
113
    #include <AvailabilityMacros.h>
114
#endif
115
116
#include <wolfssl/wolfcrypt/cpuid.h>
117
#ifdef HAVE_ENTROPY_MEMUSE
118
    #include <wolfssl/wolfcrypt/wolfentropy.h>
119
#endif
120
#ifdef HAVE_ECC
121
    #include <wolfssl/wolfcrypt/ecc.h>
122
#endif
123
#ifdef WOLFSSL_ASYNC_CRYPT
124
    #include <wolfssl/wolfcrypt/async.h>
125
#endif
126
#ifndef WC_NO_RNG
127
    /* random.h defines HAVE_HASHDRBG itself, so no HAVE_HASHDRBG test here */
128
    #include <wolfssl/wolfcrypt/random.h>
129
    #ifdef WC_RNG_LOCK_ATFORK
130
        #include <dlfcn.h>      /* the pin, which the handlers require */
131
        #include <pthread.h>    /* pthread_atfork, cancel state */
132
        #include <semaphore.h>  /* the one unlock a fork child may call */
133
        #include <errno.h>      /* EINTR from sem_wait */
134
    #endif
135
#endif
136
137
#ifdef FREESCALE_LTC_TFM
138
    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
139
#endif
140
141
#if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
142
    #include <wolfssl/wolfcrypt/port/maxim/max3266x.h>
143
#ifdef WOLF_CRYPTO_CB
144
    #include <wolfssl/wolfcrypt/port/maxim/max3266x-cryptocb.h>
145
#endif
146
#endif
147
148
#ifdef WOLFSSL_PSOC6_CRYPTO
149
    #include <wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h>
150
#endif
151
152
#ifdef MAXQ10XX_MODULE_INIT
153
    #include <wolfssl/wolfcrypt/port/maxim/maxq10xx.h>
154
#endif
155
156
#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \
157
    defined(WOLFSSL_ATECC608A) || \
158
    defined(WOLFSSL_MICROCHIP_TA100)
159
    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
160
#endif
161
#if defined(WOLFSSL_RENESAS_TSIP)
162
    #include <wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h>
163
#endif
164
#if defined(WOLFSSL_RENESAS_FSPSM)
165
    #include <wolfssl/wolfcrypt/port/Renesas/renesas_fspsm_internal.h>
166
#endif
167
#if defined(WOLFSSL_RENESAS_RX64_HASH)
168
    #include <wolfssl/wolfcrypt/port/Renesas/renesas-rx64-hw-crypt.h>
169
#endif
170
#ifdef WOLFSSL_STSAFE
171
    #include <wolfssl/wolfcrypt/port/st/stsafe.h>
172
#endif
173
174
#if defined(WOLFSSL_TROPIC01)
175
    #include <wolfssl/wolfcrypt/port/tropicsquare/tropic01.h>
176
#endif
177
178
#if defined(WOLFSSL_SILABS_CRYPTOCB)
179
    #include <wolfssl/wolfcrypt/port/silabs/silabs_cryptocb.h>
180
#endif
181
182
#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) \
183
    && !defined(WOLFCRYPT_ONLY)
184
    #include <wolfssl/openssl/evp.h>
185
#endif
186
187
#include <wolfssl/wolfcrypt/memory.h>
188
#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY)
189
    #include <wolfssl/wolfcrypt/mem_track.h>
190
#endif
191
192
#if defined(WOLFSSL_CAAM)
193
    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
194
#endif
195
#if defined(WOLFSSL_SEC_QORIQ)
196
    #include <wolfssl/wolfcrypt/port/nxp/sec_qoriq.h>
197
#endif
198
#if defined(HAVE_ARIA)
199
    #include <wolfssl/wolfcrypt/port/aria/aria-cryptocb.h>
200
#endif
201
#if defined(WOLFSSL_DEVCRYPTO)
202
    #include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
203
#endif
204
#ifdef WOLFSSL_IMXRT_DCP
205
    #include <wolfssl/wolfcrypt/port/nxp/dcp_port.h>
206
#endif
207
208
#ifdef WOLFSSL_NXP_CASPER
209
    #include <wolfssl/wolfcrypt/port/nxp/casper_port.h>
210
#endif
211
#ifdef WOLFSSL_NXP_HASHCRYPT
212
    #include <wolfssl/wolfcrypt/port/nxp/hashcrypt_port.h>
213
#endif
214
215
#ifdef WOLFSSL_TI_AM64X_R5
216
    #include <wolfssl/wolfcrypt/port/ti/ti-sa2ul_r5_port.h>
217
#endif
218
219
#ifdef WOLF_CRYPTO_CB
220
    #include <wolfssl/wolfcrypt/cryptocb.h>
221
#endif
222
223
#if defined(WOLFSSL_VERSAL_GEN2_ASU)
224
    #include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_cryptocb.h>
225
#endif
226
#if defined(WOLFSSL_ALTERA_FCS) && defined(WOLF_CRYPTO_CB)
227
#include <wolfssl/wolfcrypt/port/altera/altera_fcs.h>
228
#endif
229
230
#ifdef HAVE_INTEL_QA_SYNC
231
    #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
232
#endif
233
234
#ifdef HAVE_CAVIUM_OCTEON_SYNC
235
    #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
236
#endif
237
238
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT)
239
#include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
240
#endif
241
242
#ifdef WOLFSSL_ELS_PKC
243
#include <wolfssl/wolfcrypt/port/nxp/els_pkc_port.h>
244
#endif
245
246
#ifdef WOLFSSL_SCE
247
    #include "hal_data.h"
248
#endif
249
250
#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
251
    #include "rpcmem.h"
252
#endif
253
254
#ifdef _MSC_VER
255
    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
256
    #pragma warning(disable: 4996)
257
#endif
258
259
#if defined(WOLFSSL_HAVE_PSA)
260
    #include <wolfssl/wolfcrypt/port/psa/psa.h>
261
#endif
262
263
264
#if defined(FREERTOS) && defined(WOLFSSL_ESPIDF)
265
    #include <freertos/FreeRTOS.h>
266
    #include <freertos/task.h>
267
    /* The Espressif-specific platform include: */
268
    #include <pthread.h>
269
#endif
270
271
#if defined(WOLFSSL_ZEPHYR)
272
#if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM)
273
#include "native_rtc.h"
274
#endif
275
#endif
276
277
/* Internal APIs for counting initialization depth, with initialization/cleanup
278
 * races fully mitigated
279
 */
280
int wc_local_InitUp(wc_init_state_t *s)
281
1
{
282
1
    union wc_init_state_bitfields exp_wc_init_state, new_wc_init_state;
283
1
    exp_wc_init_state.u = WOLFSSL_ATOMIC_LOAD(*s);
284
285
    /* Mitigate races on init/shutdown by looping, unless
286
     * WC_INIT_ERROR_WHEN_CONTENDED.
287
     */
288
1
    for (;;) {
289
1
        wc_static_assert(WC_INIT_STATE_STATE_BITS < sizeof(WC_ATOMIC_UINT_ARG) * 8);
290
1
#ifdef CHAR_BIT
291
1
        wc_static_assert(WC_INIT_STATE_STATE_BITS + WC_INIT_STATE_COUNT_BITS <=
292
1
                         sizeof(WC_ATOMIC_UINT_ARG) * CHAR_BIT);
293
1
#endif
294
1
        if (exp_wc_init_state.c.count ==
295
1
            (((WC_ATOMIC_UINT_ARG)1 << WC_INIT_STATE_COUNT_BITS)
296
1
             - (WC_ATOMIC_UINT_ARG)1))
297
0
        {
298
0
            return SEQ_OVERFLOW_E;
299
0
        }
300
1
        new_wc_init_state = exp_wc_init_state;
301
1
        if (exp_wc_init_state.c.state == WC_INIT_STATE_UNINITED) {
302
1
            if (exp_wc_init_state.c.count != 0)
303
0
                return BAD_STATE_E;
304
1
            new_wc_init_state.c.state = WC_INIT_STATE_INITING;
305
1
        }
306
0
        else if (exp_wc_init_state.c.state >= WC_INIT_STATE_BAD_STATE) {
307
0
            wc_static_assert(WC_INIT_STATE_BAD_STATE > WC_INIT_STATE_UNINITED &&
308
0
                             WC_INIT_STATE_BAD_STATE > WC_INIT_STATE_INITING &&
309
0
                             WC_INIT_STATE_BAD_STATE > WC_INIT_STATE_INITED &&
310
0
                             WC_INIT_STATE_BAD_STATE > WC_INIT_STATE_CLEANING_UP);
311
0
            return BAD_STATE_E;
312
0
        }
313
0
        else {
314
0
            if (exp_wc_init_state.c.count == 0)
315
0
                return BAD_STATE_E;
316
            /* Force expected state to _INITED -- if actual value upon cmpxchg
317
             * doesn't match (normally either _INITING or _CLEANING_UP), we'll
318
             * spin until the transient state resolves to _INITED or _UNINITED
319
             * (when the competing thread calls wc_local_InitUpDone() or
320
             * wc_local_InitDownDone(), respectively).
321
             */
322
0
            exp_wc_init_state.c.state = WC_INIT_STATE_INITED;
323
0
            new_wc_init_state.c.state = WC_INIT_STATE_INITED;
324
0
        }
325
1
        ++new_wc_init_state.c.count;
326
        /* if another thread entered _STATE_INITING or _CLEANING_UP, this will
327
         * fail and spin.
328
         */
329
1
        if (wolfSSL_Atomic_Uint_CompareExchange(s,
330
1
                                                &exp_wc_init_state.u,
331
1
                                                new_wc_init_state.u))
332
1
            break;
333
#ifdef WC_INIT_ERROR_WHEN_CONTENDED
334
        return BUSY_E;
335
#else
336
0
        WC_RELAX_LONG_LOOP(); /* not really long. */
337
0
#endif
338
0
    }
339
1
    return new_wc_init_state.c.state;
340
1
}
341
342
int wc_local_InitUpDone(wc_init_state_t *s)
343
1
{
344
1
    union wc_init_state_bitfields cur_wc_init_state;
345
1
    cur_wc_init_state.u = WOLFSSL_ATOMIC_LOAD(*s);
346
1
    if (cur_wc_init_state.c.state != WC_INIT_STATE_INITING)
347
0
        return BAD_FUNC_ARG;
348
1
    cur_wc_init_state.c.state = WC_INIT_STATE_INITED;
349
    /* Note, because WC_INIT_STATE_INITING functions as a mutex on the module
350
     * state, we can use a plain _STORE() to release the module into its _INITED
351
     * state.
352
     */
353
1
    WOLFSSL_ATOMIC_STORE(*s, cur_wc_init_state.u);
354
1
    return 0;
355
1
}
356
357
int wc_local_InitDown(wc_init_state_t *s)
358
0
{
359
0
    union wc_init_state_bitfields exp_wc_init_state, new_wc_init_state;
360
361
0
    exp_wc_init_state.u = WOLFSSL_ATOMIC_LOAD(*s);
362
363
    /* Mitigate races on init/shutdown by looping, unless
364
     * WC_INIT_ERROR_WHEN_CONTENDED.
365
     */
366
0
    for (;;) {
367
0
        if (exp_wc_init_state.c.state >= WC_INIT_STATE_BAD_STATE) {
368
            /* wc_static_assert above in wc_local_InitUp() protects the logic of
369
             * the inequality test.
370
             */
371
0
            return BAD_STATE_E;
372
0
        }
373
0
        else if (exp_wc_init_state.c.state == WC_INIT_STATE_UNINITED) {
374
0
            if (exp_wc_init_state.c.count == 0) {
375
                /* thread attempted to wc_local_InitDown() without a matching
376
                 * previous wc_local_InitUp().
377
                 */
378
0
                return ALREADY_E; /* backward compat */
379
0
            }
380
0
            else {
381
                /* nonzero .count with _STATE_UNINITED is impossible. */
382
0
                return BAD_STATE_E;
383
0
            }
384
0
        }
385
0
        else if (exp_wc_init_state.c.state == WC_INIT_STATE_INITING) {
386
            /* _INITING is impossible here unless a thread calls
387
             * wc_local_InitDown() before (or without) successfully calling
388
             * wc_local_InitUpDone().
389
             */
390
0
            return BAD_FUNC_ARG;
391
0
        }
392
0
        else if (exp_wc_init_state.c.state == WC_INIT_STATE_CLEANING_UP) {
393
0
            if (exp_wc_init_state.c.count == 1) {
394
                /* thread attempted to wc_local_InitDown() without a matching
395
                 * previous wc_local_InitUp().
396
                 */
397
0
                return ALREADY_E; /* backward compat */
398
0
            }
399
0
            else {
400
                /* _CLEANING_UP is impossible with .count != 1. */
401
0
                return BAD_STATE_E;
402
0
            }
403
0
        }
404
0
        else if (exp_wc_init_state.c.count == 0) {
405
            /* zero count with state != _UNINITED is impossible. */
406
0
            return BAD_STATE_E;
407
0
        }
408
0
        new_wc_init_state = exp_wc_init_state;
409
0
        if (exp_wc_init_state.c.count == 1) {
410
0
            new_wc_init_state.c.state = WC_INIT_STATE_CLEANING_UP;
411
            /* don't zero until end. */
412
0
        }
413
0
        else
414
0
            --new_wc_init_state.c.count;
415
0
        if (wolfSSL_Atomic_Uint_CompareExchange(s,
416
0
                                                &exp_wc_init_state.u,
417
0
                                                new_wc_init_state.u))
418
0
            break;
419
#ifdef WC_INIT_ERROR_WHEN_CONTENDED
420
        return BUSY_E;
421
#else
422
0
        WC_RELAX_LONG_LOOP(); /* not really long. */
423
0
#endif
424
0
    }
425
426
0
    return new_wc_init_state.c.state;
427
0
}
428
429
int wc_local_InitDownDone(wc_init_state_t *s)
430
0
{
431
0
    union wc_init_state_bitfields cur_wc_init_state;
432
0
    cur_wc_init_state.u = WOLFSSL_ATOMIC_LOAD(*s);
433
0
    if (cur_wc_init_state.c.state != WC_INIT_STATE_CLEANING_UP)
434
0
        return BAD_FUNC_ARG;
435
0
    cur_wc_init_state.c.state = WC_INIT_STATE_UNINITED;
436
0
    cur_wc_init_state.c.count = 0;
437
    /* Note, because WC_INIT_STATE_CLEANING_UP functions as a mutex on the
438
     * module state, we can use a plain _STORE() to release the module into its
439
     * _UNINITED state.
440
     */
441
0
    WOLFSSL_ATOMIC_STORE(*s, cur_wc_init_state.u);
442
0
    return 0;
443
0
}
444
445
#ifdef WOLF_CRYPTO_CB
446
static int wc_local_InitDownAbort(wc_init_state_t* s)
447
{
448
    union wc_init_state_bitfields cur_wc_init_state;
449
450
    cur_wc_init_state.u = WOLFSSL_ATOMIC_LOAD(*s);
451
    if (cur_wc_init_state.c.state != WC_INIT_STATE_CLEANING_UP ||
452
        cur_wc_init_state.c.count != 1) {
453
        return BAD_STATE_E;
454
    }
455
    cur_wc_init_state.c.state = WC_INIT_STATE_INITED;
456
    WOLFSSL_ATOMIC_STORE(*s, cur_wc_init_state.u);
457
    return 0;
458
}
459
#endif /* WOLF_CRYPTO_CB */
460
461
static WC_DECLARE_INIT_STATE(wolfcrypt_init_state);
462
463
#if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT)
464
int aarch64_use_sb = 0;
465
#endif
466
467
#ifdef WC_RNG_HAVE_AUTO_LOCK
468
/* Cancellation off while a lock is held, so a cancel cannot strand it.  Where
469
 * the platform has no cancellation both are empty and the value is unused.
470
 */
471
WOLFSSL_LOCAL int wc_CancelDisable(void)
472
128k
{
473
128k
#ifdef PTHREAD_CANCEL_DISABLE
474
128k
    int old = PTHREAD_CANCEL_ENABLE;   /* what a failed call leaves behind */
475
128k
    (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
476
#else
477
    int old = 0;
478
#endif
479
128k
    return old;
480
128k
}
481
482
WOLFSSL_LOCAL void wc_CancelRestore(int state)
483
128k
{
484
128k
#ifdef PTHREAD_CANCEL_DISABLE
485
128k
    (void)pthread_setcancelstate(state, NULL);
486
#else
487
    (void)state;
488
#endif
489
128k
}
490
#endif /* WC_RNG_HAVE_AUTO_LOCK */
491
492
#ifdef WC_RNG_LOCK_ATFORK
493
#if !defined(RTLD_NOLOAD) || !defined(RTLD_NODELETE)
494
    #error "WC_RNG_AUTOFORK needs RTLD_NOLOAD and RTLD_NODELETE"
495
#endif
496
/* The fork handlers can never be unregistered, so the image that holds them
497
 * is pinned against dlclose() before they are registered. */
498
WOLFSSL_LOCAL void wc_PinImage(void* fn)
499
1
{
500
1
    Dl_info info;
501
1
    const char* name;   /* a pointer on most libcs, an array on Cygwin */
502
1
    if (dladdr(fn, &info) == 0 || (name = info.dli_fname) == NULL ||
503
1
        name[0] == '\0' ||
504
1
        dlopen(name, RTLD_NOLOAD | RTLD_NODELETE | RTLD_LAZY) == NULL) {
505
        /* no dlopen() handle means no dlclose() can reach this image */
506
1
        WOLFSSL_MSG("RNG fork handlers: no dlopen handle, nothing to pin");
507
1
    }
508
1
}
509
510
/* One lock per object, held with an unnamed semaphore so a fork child can
511
 * release it: sem_post() is async-signal-safe, pthread_mutex_unlock() is not. */
512
struct wc_ForkLock {
513
    sem_t sem;
514
    void* heap;
515
    struct wc_ForkLock* next;
516
    struct wc_ForkLock** prev;   /* the link that leads here */
517
    /* Read once per lock acquire, written once per fork: a load, never a
518
     * read-modify-write, so no contended line and no bus traffic. */
519
    wolfSSL_Atomic_Int broken;   /* fails closed; a lone child or dead sem */
520
    /* Set by prepare, cleared by parent and child: no other thread reads it. */
521
    int forkState;   /* one of the WC_FORK_LOCK_* values */
522
    int cancel;   /* the holder's cancel state, back on exit */
523
};
524
525
/* Real thread local storage, not the do-nothing THREAD_LS_T fallback. */
526
#if defined(HAVE_THREAD_LS) && !defined(NO_THREAD_LS) && \
527
    !defined(FREERTOS) && !defined(FREERTOS_TCP) && !defined(WOLFSSL_ZEPHYR)
528
    #define WC_FORK_LOCK_HAVE_TLS
529
#endif
530
531
#ifndef WC_FORK_LOCK_HAVE_TLS
532
    /* Without it the prepare handler cannot tell which locks this thread
533
     * holds, and a fork() from a seed callback would wait on itself. */
534
    #error "the RNG fork handlers need thread local storage"
535
#endif
536
/* What this thread holds.  Only this thread touches it, so no atomics.
537
 * The library never nests these; the spare slots cover a callback that does. */
538
118k
#define WC_FORK_MINE_MAX 4   /* past this, taking the lock is refused */
539
static THREAD_LS_T wc_ForkLock* forkMine[WC_FORK_MINE_MAX];
540
541
/* Returns 0 when there is no slot left to record it in. */
542
static int ForkMineAdd(wc_ForkLock* lock)
543
59.4k
{
544
59.4k
    int i;
545
59.4k
    for (i = 0; i < WC_FORK_MINE_MAX; i++) {
546
59.4k
        if (forkMine[i] == NULL) {
547
59.4k
            forkMine[i] = lock;
548
59.4k
            return 1;
549
59.4k
        }
550
59.4k
    }
551
0
    return 0;
552
59.4k
}
553
554
static void ForkMineDrop(wc_ForkLock* lock)
555
59.4k
{
556
59.4k
    int i;
557
59.4k
    for (i = 0; i < WC_FORK_MINE_MAX; i++) {
558
59.4k
        if (forkMine[i] == lock) {
559
59.4k
            forkMine[i] = NULL;
560
59.4k
            return;
561
59.4k
        }
562
59.4k
    }
563
59.4k
}
564
565
/* Does the calling thread hold this one? */
566
static int ForkMineHeld(const wc_ForkLock* lock)
567
0
{
568
0
    int i;
569
0
    for (i = 0; i < WC_FORK_MINE_MAX; i++) {
570
0
        if (forkMine[i] == lock) {
571
0
            return 1;
572
0
        }
573
0
    }
574
0
    return 0;
575
0
}
576
577
static wc_ForkLock* forkList = NULL;   /* every live lock, under forkListSem */
578
static sem_t forkListSem;
579
static wolfSSL_Atomic_Int forkListDead =
580
    WOLFSSL_ATOMIC_INITIALIZER(0);   /* registry unusable: handlers back off */
581
static pthread_once_t forkOnce = PTHREAD_ONCE_INIT;
582
static int forkOnceRet = 0;
583
584
/* sem_wait() is a cancellation point; a cancel here would strand the lock. */
585
static int ForkSemWait(sem_t* s)
586
69.1k
{
587
69.1k
    int ret = 0;
588
69.1k
    int old = wc_CancelDisable();
589
69.1k
    while (sem_wait(s) != 0) {
590
0
        if (errno != EINTR) {
591
0
            ret = BAD_MUTEX_E;
592
0
            break;
593
0
        }
594
0
    }
595
69.1k
    wc_CancelRestore(old);
596
69.1k
    return ret;
597
69.1k
}
598
599
/* Before fork(): the forking thread takes the registry and every lock. */
600
static void ForkPrepare(void)
601
0
{
602
0
    wc_ForkLock* n;
603
0
    if (WOLFSSL_ATOMIC_LOAD(forkListDead))
604
0
        return;
605
0
    if (ForkSemWait(&forkListSem) != 0) {
606
0
        WOLFSSL_ATOMIC_STORE(forkListDead, 1); /* nothing held, and never again */
607
0
        return;
608
0
    }
609
0
    for (n = forkList; n != NULL; n = n->next) {
610
0
        if (WOLFSSL_ATOMIC_LOAD(n->broken)) {
611
0
            continue;
612
0
        }
613
        /* Waiting on one this thread already holds would never return.  The
614
         * child's only thread is this one, and it releases it as usual. */
615
0
        if (ForkMineHeld(n)) {
616
0
            n->forkState = WC_FORK_LOCK_OWNED;
617
0
            continue;
618
0
        }
619
0
        if (ForkSemWait(&n->sem) != 0) {
620
0
            WOLFSSL_ATOMIC_STORE(n->broken, 1);
621
0
        }
622
0
        else {
623
0
            n->forkState = WC_FORK_LOCK_TAKEN;
624
0
        }
625
0
    }
626
0
}
627
628
/* After fork() in the parent: give back exactly what prepare took.
629
 * Re-reading broken here could post a lock prepare never held. */
630
static void ForkParent(void)
631
0
{
632
0
    wc_ForkLock* n;
633
0
    if (WOLFSSL_ATOMIC_LOAD(forkListDead))
634
0
        return;
635
0
    for (n = forkList; n != NULL; n = n->next) {
636
0
        if (n->forkState == WC_FORK_LOCK_TAKEN) {
637
0
            (void)sem_post(&n->sem);
638
0
        }
639
        /* An owned one needs nothing: its holder still has it. */
640
0
        n->forkState = WC_FORK_LOCK_UNTAKEN;
641
0
    }
642
0
    (void)sem_post(&forkListSem);
643
0
}
644
645
/* Child after fork(): stores and sem_post() only, all POSIX allows here.
646
 * An untaken lock fails closed; an owned one is freed by this thread. */
647
static void ForkChild(void)
648
0
{
649
0
    wc_ForkLock* n;
650
0
    for (n = forkList; n != NULL; n = n->next) {   /* forward links stay whole */
651
0
        if (n->forkState == WC_FORK_LOCK_TAKEN) {
652
0
            (void)sem_post(&n->sem);
653
0
        }
654
0
        else if (n->forkState == WC_FORK_LOCK_UNTAKEN) {
655
0
            WOLFSSL_ATOMIC_STORE(n->broken, 1);
656
0
        }
657
0
        n->forkState = WC_FORK_LOCK_UNTAKEN;
658
0
    }
659
0
    if (!WOLFSSL_ATOMIC_LOAD(forkListDead))
660
0
        (void)sem_post(&forkListSem);
661
0
}
662
663
static void ForkLockInitOnce(void)
664
1
{
665
    /* pin first: the handlers can never be unregistered */
666
1
    wc_PinImage((void*)(wc_ptr_t)ForkPrepare);
667
1
    forkOnceRet = (sem_init(&forkListSem, 0, 1) == 0) ? 0 : BAD_MUTEX_E;
668
1
    if (forkOnceRet == 0 &&
669
1
        pthread_atfork(ForkPrepare, ForkParent, ForkChild) != 0)
670
0
    {
671
0
        (void)sem_destroy(&forkListSem);
672
0
        forkOnceRet = MEMORY_E;
673
0
    }
674
1
}
675
676
WOLFSSL_LOCAL int wc_ForkLockInit(void)
677
4.87k
{
678
4.87k
    (void)pthread_once(&forkOnce, ForkLockInitOnce);
679
4.87k
    return forkOnceRet;
680
4.87k
}
681
682
WOLFSSL_LOCAL int wc_ForkLock_New(wc_ForkLock** lock, void* heap)
683
4.87k
{
684
4.87k
    wc_ForkLock* n;
685
4.87k
    int ret = wc_ForkLockInit();
686
4.87k
    if (ret != 0)
687
0
        return ret;
688
4.87k
    if (WOLFSSL_ATOMIC_LOAD(forkListDead)) {
689
0
        WOLFSSL_MSG("wc_ForkLock_New: registry dead since a fork");
690
0
        return BAD_MUTEX_E;
691
0
    }
692
4.87k
    n = (wc_ForkLock*)XMALLOC(sizeof(*n), heap, DYNAMIC_TYPE_RNG);
693
4.87k
    if (n == NULL)
694
0
        return MEMORY_E;
695
4.87k
    XMEMSET(n, 0, sizeof(*n));
696
4.87k
    n->heap = heap;
697
4.87k
    if (ForkSemWait(&forkListSem) != 0) {
698
0
        XFREE(n, heap, DYNAMIC_TYPE_RNG);
699
0
        return BAD_MUTEX_E;
700
0
    }
701
4.87k
    ret = (sem_init(&n->sem, 0, 1) == 0) ? 0 : BAD_MUTEX_E;
702
4.87k
    if (ret == 0) {
703
4.87k
        n->next = forkList;
704
4.87k
        n->prev = &forkList;
705
4.87k
        if (forkList != NULL)
706
0
            forkList->prev = &n->next;
707
4.87k
        forkList = n;
708
4.87k
    }
709
4.87k
    (void)sem_post(&forkListSem);
710
4.87k
    if (ret != 0) {
711
0
        XFREE(n, heap, DYNAMIC_TYPE_RNG);
712
0
        return ret;
713
0
    }
714
4.87k
    *lock = n;
715
4.87k
    return 0;
716
4.87k
}
717
718
/* Safe on a NULL lock that was never created. */
719
WOLFSSL_LOCAL void wc_ForkLock_Free(wc_ForkLock** lock)
720
4.87k
{
721
4.87k
    wc_ForkLock* n;
722
4.87k
    if (lock == NULL || *lock == NULL)
723
0
        return;
724
4.87k
    n = *lock;
725
4.87k
    if (WOLFSSL_ATOMIC_LOAD(forkListDead) || ForkSemWait(&forkListSem) != 0) {
726
        /* No registry to unlink under, so the node stays on the list and
727
         * is leaked; broken keeps every later handler off it. */
728
0
        WOLFSSL_ATOMIC_STORE(n->broken, 1);
729
0
        WOLFSSL_MSG("wc_ForkLock_Free: registry unavailable, node leaked");
730
0
        *lock = NULL;
731
0
        return;
732
0
    }
733
4.87k
    *n->prev = n->next;
734
4.87k
    if (n->next != NULL)
735
0
        n->next->prev = n->prev;
736
4.87k
    (void)sem_post(&forkListSem);
737
4.87k
    (void)sem_destroy(&n->sem);
738
4.87k
    XFREE(n, n->heap, DYNAMIC_TYPE_RNG);
739
4.87k
    *lock = NULL;
740
4.87k
}
741
742
/* Cancellation stays off while the lock is held: a reseed reads a device,
743
 * a cancellation point, and a cancelled holder would strand every fork(). */
744
WOLFSSL_API int wc_ForkLock_Enter(wc_ForkLock* lock)
745
59.4k
{
746
59.4k
    int old;
747
59.4k
    int ret;
748
59.4k
    if (lock == NULL)
749
0
        return 0;
750
59.4k
    if (WOLFSSL_ATOMIC_LOAD(lock->broken))
751
0
        return BAD_MUTEX_E;
752
59.4k
    old = wc_CancelDisable();
753
59.4k
    ret = ForkSemWait(&lock->sem);
754
59.4k
    if (ret != 0) {
755
0
        wc_CancelRestore(old);
756
0
    }
757
59.4k
    else if (!ForkMineAdd(lock)) {
758
        /* Unrecorded means prepare would wait on a lock this thread holds,
759
         * so refuse it here rather than hand back a fork() that hangs. */
760
0
        (void)sem_post(&lock->sem);
761
0
        wc_CancelRestore(old);
762
0
        ret = BAD_MUTEX_E;
763
0
    }
764
59.4k
    else {
765
59.4k
        lock->cancel = old;
766
59.4k
    }
767
59.4k
    return ret;
768
59.4k
}
769
770
WOLFSSL_API   void wc_ForkLock_Exit(wc_ForkLock* lock)
771
59.4k
{
772
59.4k
    int old;
773
59.4k
    if (lock == NULL)
774
0
        return;
775
59.4k
    old = lock->cancel;
776
59.4k
    ForkMineDrop(lock);
777
59.4k
    (void)sem_post(&lock->sem);
778
59.4k
    wc_CancelRestore(old);
779
59.4k
}
780
781
WOLFSSL_API   void wc_ForkLock_SetBroken(wc_ForkLock* lock, int broken)
782
0
{
783
0
    if (lock != NULL)
784
0
        WOLFSSL_ATOMIC_STORE(lock->broken, broken);
785
0
}
786
#endif
787
788
#ifdef WC_BARRIER_DATA_USES_SINK
789
/* Callee of the portable WC_BARRIER_DATA() arm. It is reached through a
790
 * pointer read with a volatile load, so link time optimization cannot see
791
 * that the body is empty and drop the escape of the buffer address. */
792
static void wc_BarrierDataSinkImpl(void* p)
793
{
794
    (void)p;
795
}
796
static void (* const wc_BarrierDataSinkPtr)(void*) = wc_BarrierDataSinkImpl;
797
798
WC_NO_INLINE void wc_BarrierDataSink(void* p)
799
{
800
    void (*fn)(void*) =
801
        *(void (* const volatile *)(void*))&wc_BarrierDataSinkPtr;
802
    fn(p);
803
}
804
#endif /* WC_BARRIER_DATA_USES_SINK */
805
806
/* Used to initialize state for wolfcrypt
807
   return 0 on success
808
 */
809
WOLFSSL_ABI
810
int wolfCrypt_Init(void)
811
1
{
812
1
    int ret;
813
1
#if defined(HAVE_THREAD_LS) && !defined(NO_THREAD_LS) && defined(__GNUC__)
814
    /* If thread-local storage is available, use it to prevent deadlock on
815
     * recursion.  We only do this when __GNUC__ -- this code is known to cause
816
     * internal compiler faults on Watcom, and is probably problematic on other
817
     * non-_GNUC__ targets besides.
818
     */
819
1
    static THREAD_LS_T int in_init = 0;
820
1
    if (in_init)
821
0
        return DEADLOCK_AVERTED_E;
822
1
    #define WOLFCRYPT_INIT_RAISE_BAD_STATE() do {                \
823
0
            in_init = 0;                                         \
824
0
            WC_INIT_STATE_RAISE_BAD_STATE(wolfcrypt_init_state); \
825
0
            return ret;                                          \
826
0
    } while (0)
827
#else
828
    #define WOLFCRYPT_INIT_RAISE_BAD_STATE() do {                \
829
            WC_INIT_STATE_RAISE_BAD_STATE(wolfcrypt_init_state); \
830
            return ret;                                          \
831
    } while (0)
832
#endif
833
834
1
    ret = wc_local_InitUp(&wolfcrypt_init_state);
835
1
    if (ret < 0)
836
0
        return ret;
837
1
    else if (ret == WC_INIT_STATE_INITED)
838
0
        return 0;
839
1
    else {
840
1
        WOLFSSL_ENTER("wolfCrypt_Init");
841
842
1
#if defined(HAVE_THREAD_LS) && !defined(NO_THREAD_LS) && defined(__GNUC__)
843
1
        in_init = 1;
844
1
#endif
845
846
    #if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT)
847
        aarch64_use_sb = IS_AARCH64_SB(cpuid_get_flags());
848
    #endif
849
850
    #ifdef WOLFSSL_CHECK_MEM_ZERO
851
        /* Initialize the mutex for access to the list of memory locations that
852
         * must be freed. */
853
        wc_MemZero_Init();
854
    #endif
855
    #ifdef WOLFSSL_MEM_FAIL_COUNT
856
        wc_MemFailCount_Init();
857
    #endif
858
859
    #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
860
        {
861
            word32 rngMallocFail;
862
            time_t seed = time(NULL);
863
            srand((word32)seed);
864
            rngMallocFail = rand() % 2000; /* max 2000 */
865
            fprintf(stderr, "\n--- RNG MALLOC FAIL AT %u ---\n", rngMallocFail);
866
            wolfSSL_SetMemFailCount(rngMallocFail);
867
        }
868
    #endif
869
870
    #ifdef WOLF_CRYPTO_CB
871
        wc_CryptoCb_Init();
872
    #endif
873
874
    #ifdef WOLFSSL_ASYNC_CRYPT
875
        ret = wolfAsync_HardwareStart();
876
        if (ret != 0) {
877
            WOLFSSL_MSG("Async hardware start failed");
878
            /* don't return failure, allow operation to continue */
879
        }
880
    #endif
881
882
    #if defined(WOLFSSL_RENESAS_TSIP)
883
        ret = tsip_Open( );
884
        if( ret != TSIP_SUCCESS ) {
885
            WOLFSSL_MSG("RENESAS TSIP Open failed");
886
            /* not return 1 since WOLFSSL_SUCCESS=1*/
887
            ret = WC_FAILURE;
888
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
889
        }
890
    #endif
891
892
    #if defined(WOLFSSL_RENESAS_RX64_HASH)
893
    ret = rx64_hw_Open();
894
    if( ret != 0 ) {
895
        WOLFSSL_MSG("Renesas RX64 HW Open failed");
896
        /* not return 1 since WOLFSSL_SUCCESS=1*/
897
        ret = WC_FAILURE;
898
        WOLFCRYPT_INIT_RAISE_BAD_STATE();
899
    }
900
    #endif
901
902
    #if defined(WOLFSSL_RENESAS_FSPSM)
903
        ret = wc_fspsm_Open( );
904
        if( ret != FSP_SUCCESS ) {
905
            WOLFSSL_MSG("RENESAS SCE Open failed");
906
            /* not return 1 since WOLFSSL_SUCCESS=1*/
907
            ret = WC_FAILURE;
908
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
909
        }
910
    #endif
911
912
    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
913
        ret = InitMemoryTracker();
914
        if (ret != 0) {
915
            WOLFSSL_MSG("InitMemoryTracker failed");
916
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
917
        }
918
    #endif
919
920
    #if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WOLFSSL_LINUXKM)
921
        ret = wc_linuxkm_allocate_svr_states();
922
        if (ret != 0) {
923
            WOLFSSL_MSG("wc_linuxkm_allocate_svr_states failed");
924
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
925
        }
926
    #endif
927
928
    #if WOLFSSL_CRYPT_HW_MUTEX
929
        /* If crypto hardware mutex protection is enabled, then initialize it */
930
        ret = wolfSSL_CryptHwMutexInit();
931
        if (ret != 0) {
932
            WOLFSSL_MSG("Hw crypt mutex init failed");
933
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
934
        }
935
    #endif
936
937
1
    #ifdef WC_RNG_LOCK_ATFORK
938
        /* here, before the app has threads, so no fork can race it */
939
1
        ret = wc_ForkLockInit();
940
1
        if (ret != 0) {
941
0
            WOLFSSL_MSG("RNG fork handler registration failed");
942
0
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
943
0
        }
944
1
    #endif
945
946
    #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC)
947
        ret = ksdk_port_init();
948
        if (ret != 0) {
949
            WOLFSSL_MSG("KSDK port init failed");
950
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
951
        }
952
    #endif
953
954
    /* Crypto Callbacks only works on AES for MAX32666/5 HW */
955
    #if defined(MAX3266X_AES) && defined(WOLF_CRYPTO_CB)
956
        ret = wc_CryptoCb_RegisterDevice(WOLFSSL_MAX3266X_DEVID, wc_MxcCryptoCb,
957
                                            NULL);
958
        if (ret != 0) {
959
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
960
        }
961
    #endif
962
963
    /* Register the Versal Gen2 ASU device so wolfCrypt operations route to the
964
     * ASU hardware. Registering also brings the ASU client up. */
965
    #if defined(WOLFSSL_VERSAL_GEN2_ASU) && defined(WOLF_CRYPTO_CB)
966
        ret = wc_AsuCryptoCb_RegisterDevice(WOLFSSL_VERSAL_GEN2_ASU_DEVID);
967
        if (ret != 0) {
968
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
969
        }
970
    #endif
971
972
    /* Register the Silicon Labs Secure Element device so wolfCrypt operations
973
     * route to the SE. sl_se_init() runs further down in this function. */
974
    #if defined(WOLFSSL_SILABS_CRYPTOCB) && defined(WOLF_CRYPTO_CB)
975
        ret = wc_SilabsCryptoCb_RegisterDevice(WOLFSSL_SILABS_DEVID);
976
        if (ret != 0) {
977
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
978
        }
979
    #endif
980
    /* The Agilex 5 SDM is an optional accelerator: contexts on its devId use
981
     * software when it is absent, and its device key APIs report the error. */
982
    #if defined(WOLFSSL_ALTERA_FCS) && defined(WOLF_CRYPTO_CB)
983
        ret = wc_AlteraFcsCryptoCb_RegisterDeviceMask(
984
                WOLFSSL_ALTERA_FCS_DEVID, WOLFSSL_ALTERA_FCS_AUTO_MASK);
985
        if (ret != 0) {
986
            WOLFSSL_MSG("Altera FCS unavailable; using software fallback");
987
            ret = 0;
988
        }
989
    #endif
990
    #if defined(MAX3266X_RTC)
991
        ret = wc_MXC_RTC_Init();
992
        if (ret != 0) {
993
            WOLFSSL_MSG("MXC RTC Init Failed");
994
            ret = WC_HW_E;
995
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
996
        }
997
    #endif
998
999
    #if defined(WOLFSSL_TI_AM64X_R5)
1000
        ret = ti_sa2ul_port_init();
1001
        if (ret != 0) {
1002
            WOLFSSL_MSG("TI AM64x Init Failed");
1003
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1004
        }
1005
    #endif
1006
1007
    #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \
1008
        defined(WOLFSSL_ATECC608A) || defined(WOLFSSL_MICROCHIP_TA100)
1009
        ret = atmel_init();
1010
        if (ret != 0) {
1011
            WOLFSSL_MSG("CryptoAuthLib init failed");
1012
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1013
        }
1014
    #endif
1015
    #ifdef WOLFSSL_STSAFE
1016
        ret = stsafe_interface_init();
1017
        if (ret != 0) {
1018
            WOLFSSL_MSG("STSAFE init failed");
1019
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1020
        }
1021
    #endif
1022
    #if defined(WOLFSSL_TROPIC01)
1023
        ret = Tropic01_Init();
1024
        if (ret != 0) {
1025
            WOLFSSL_MSG("Tropic01 init failed");
1026
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1027
        }
1028
    #endif
1029
    #if defined(WOLFSSL_PSOC6_CRYPTO)
1030
        ret = psoc6_crypto_port_init();
1031
        if (ret != 0) {
1032
            WOLFSSL_MSG("PSoC6 crypto engine init failed");
1033
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1034
        }
1035
    #endif
1036
1037
    #ifdef MAXQ10XX_MODULE_INIT
1038
        ret = maxq10xx_port_init();
1039
        if (ret != 0) {
1040
            WOLFSSL_MSG("MAXQ10xx port init failed");
1041
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1042
        }
1043
    #endif
1044
1045
    #ifdef WOLFSSL_SILABS_SE_TYPES
1046
        /* init handles if it is already initialized */
1047
        ret = sl_se_init();
1048
        if (ret != 0) {
1049
            WOLFSSL_MSG("SiLabs SE Manager init failed");
1050
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1051
        }
1052
    #endif
1053
1054
    #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT)
1055
        /* An application may need runtime SCP03 keys to open the SE05x
1056
         * before calling wolfCrypt_Init(). Keep that configured session
1057
         * instead of trying to replace it with the compiled-in defaults. */
1058
        if (wc_se050_get_session() == NULL) {
1059
            ret = wc_se050_init(NULL);
1060
            if (ret != 0) {
1061
                WOLFSSL_MSG("SE050 init failed");
1062
                WOLFCRYPT_INIT_RAISE_BAD_STATE();
1063
            }
1064
        }
1065
    #endif
1066
1067
    #ifdef WOLFSSL_ELS_PKC
1068
        ret = wc_ElsPkc_Init();
1069
        if (ret != 0) {
1070
            WOLFSSL_MSG("EdgeLock (ELS/PKC) init failed");
1071
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1072
        }
1073
    #endif
1074
1075
    #ifdef WOLFSSL_ARMASM
1076
        WOLFSSL_MSG("Using ARM hardware acceleration");
1077
    #endif
1078
1079
    #ifdef WOLFSSL_AFALG
1080
        WOLFSSL_MSG("Using AF_ALG for crypto acceleration");
1081
    #endif
1082
1083
    #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA)
1084
        wolfSSL_EVP_init();
1085
    #endif
1086
1087
    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
1088
        if ((ret = wc_LoggingInit()) != 0) {
1089
            WOLFSSL_MSG("Error creating logging mutex");
1090
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1091
        }
1092
    #endif
1093
1094
    #if defined(WOLFSSL_HAVE_PSA)
1095
        if ((ret = wc_psa_init()) != 0) {
1096
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1097
        }
1098
    #endif
1099
1100
    #if defined(USE_WINDOWS_API) && defined(WIN_REUSE_CRYPT_HANDLE) && \
1101
        !defined(CUSTOM_RAND_GENERATE_BLOCK)
1102
        /* A failure here should not happen, but if it does the actual RNG seed
1103
         * call will fail. This init is for a shared crypt provider handle for
1104
         * RNG */
1105
        (void)wc_WinCryptHandleInit();
1106
    #endif
1107
1108
    #ifdef HAVE_ENTROPY_MEMUSE
1109
        ret = Entropy_Init();
1110
        if (ret != 0) {
1111
            WOLFSSL_MSG("Error initializing entropy");
1112
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1113
        }
1114
    #endif
1115
1116
1
#ifdef HAVE_ECC
1117
    #ifdef FP_ECC
1118
        wc_ecc_fp_init();
1119
    #endif
1120
    #ifdef ECC_CACHE_CURVE
1121
        if ((ret = wc_ecc_curve_cache_init()) != 0) {
1122
            WOLFSSL_MSG("Error creating curve cache");
1123
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1124
        }
1125
    #endif
1126
    #if defined(HAVE_OID_ENCODING) && (!defined(HAVE_FIPS) || \
1127
            (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0)))
1128
        if ((ret = wc_ecc_oid_cache_init()) != 0) {
1129
            WOLFSSL_MSG("Error creating ECC oid cache");
1130
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1131
        }
1132
    #endif
1133
1
#endif
1134
1135
#ifdef WOLFSSL_SCE
1136
        ret = (int)WOLFSSL_SCE_GSCE_HANDLE.p_api->open(
1137
                WOLFSSL_SCE_GSCE_HANDLE.p_ctrl, WOLFSSL_SCE_GSCE_HANDLE.p_cfg);
1138
        if (ret == SSP_ERR_CRYPTO_SCE_ALREADY_OPEN) {
1139
            WOLFSSL_MSG("SCE already open");
1140
            ret = 0;
1141
        }
1142
        if (ret != SSP_SUCCESS) {
1143
            WOLFSSL_MSG("Error opening SCE");
1144
            ret = WC_FAILURE;
1145
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1146
        }
1147
#endif
1148
1149
#if defined(WOLFSSL_DEVCRYPTO)
1150
        if ((ret = wc_DevCryptoInit()) != 0) {
1151
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1152
        }
1153
#endif
1154
1155
#if defined(WOLFSSL_CAAM)
1156
        if ((ret = wc_caamInit()) != 0) {
1157
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1158
        }
1159
#endif
1160
1161
#if defined(WOLFSSL_SEC_QORIQ)
1162
        /* A part without the security engine is not an error: the SEC is
1163
         * only fitted on the "E" orderable variants, and everything simply
1164
         * stays in software there. */
1165
        ret = wc_SecQoriqInit();
1166
        if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
1167
            ret = 0;
1168
        }
1169
        else if (ret != 0) {
1170
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1171
        }
1172
#endif
1173
1174
#if defined(HAVE_ARIA)
1175
        if ((ret = wc_AriaInit()) != 0) {
1176
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1177
        }
1178
#endif
1179
1180
#ifdef WOLFSSL_IMXRT_DCP
1181
        if ((ret = wc_dcp_init()) != 0) {
1182
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1183
        }
1184
#endif
1185
1186
#ifdef WOLFSSL_NXP_CASPER
1187
        if ((ret = wc_casper_init()) != 0) {
1188
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1189
        }
1190
#endif
1191
#ifdef WOLFSSL_NXP_HASHCRYPT
1192
        if ((ret = wc_hashcrypt_init()) != 0) {
1193
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1194
        }
1195
#endif
1196
1197
#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
1198
        if ((ret = wolfSSL_InitHandle()) != 0) {
1199
            WOLFCRYPT_INIT_RAISE_BAD_STATE();
1200
        }
1201
        rpcmem_init();
1202
#endif
1203
1204
1205
1
#undef WOLFCRYPT_INIT_RAISE_BAD_STATE
1206
1207
1
#if defined(HAVE_THREAD_LS) && !defined(NO_THREAD_LS) && defined(__GNUC__)
1208
1
        in_init = 0;
1209
1
#endif
1210
1
        return wc_local_InitUpDone(&wolfcrypt_init_state);
1211
1
    }
1212
    /* not reached */
1213
1
}
1214
1215
#if defined(WOLFSSL_TRACK_MEMORY_VERBOSE) && !defined(WOLFSSL_STATIC_MEMORY)
1216
long wolfCrypt_heap_peakAllocs_checkpoint(void) {
1217
    long ret = ourMemStats.peakAllocsTripOdometer;
1218
    ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs -
1219
        ourMemStats.totalDeallocs;
1220
    return ret;
1221
}
1222
long wolfCrypt_heap_peakBytes_checkpoint(void) {
1223
    long ret = ourMemStats.peakBytesTripOdometer;
1224
    ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes;
1225
    return ret;
1226
}
1227
#endif
1228
1229
/* return success value is the same as wolfCrypt_Init */
1230
WOLFSSL_ABI
1231
int wolfCrypt_Cleanup(void)
1232
0
{
1233
0
    int ret;
1234
1235
0
    ret = wc_local_InitDown(&wolfcrypt_init_state);
1236
0
    if (ret < 0) {
1237
0
        if (ret == WC_NO_ERR_TRACE(ALREADY_E))
1238
0
            WOLFSSL_MSG("wolfCrypt_Cleanup() called during or after prior final cleanup.");
1239
0
        else if (ret == WC_NO_ERR_TRACE(BAD_STATE_E))
1240
0
            WOLFSSL_MSG("wolfCrypt_Cleanup() failed: bad internal state.");
1241
#ifdef WC_INIT_ERROR_WHEN_CONTENDED
1242
        else if (ret == WC_NO_ERR_TRACE(BUSY_E))
1243
            WOLFSSL_MSG("wolfCrypt_Cleanup() failed with BUSY_E -- retry.");
1244
#endif
1245
0
        else
1246
0
            WOLFSSL_MSG("wolfCrypt_Cleanup() failed with unexpected error.");
1247
0
        return ret;
1248
0
    }
1249
0
    else if (ret == WC_INIT_STATE_INITED)
1250
0
        return 0;
1251
0
    else {
1252
#ifdef WOLF_CRYPTO_CB
1253
        /* Altera FCS unregisters through this loop too, so an abort on a
1254
         * different device's BUSY_E leaves its SDM session intact. */
1255
        ret = wc_CryptoCb_Cleanup();
1256
        if (ret != 0) {
1257
            int ret2 = wc_local_InitDownAbort(&wolfcrypt_init_state);
1258
            return (ret2 == 0) ? ret : ret2;
1259
        }
1260
#endif
1261
0
        ret = 0;
1262
1263
0
        WOLFSSL_ENTER("wolfCrypt_Cleanup");
1264
1265
0
#ifdef HAVE_ECC
1266
    #ifdef FP_ECC
1267
        wc_ecc_fp_free();
1268
    #endif
1269
    #ifdef ECC_CACHE_CURVE
1270
        wc_ecc_curve_cache_free();
1271
    #endif
1272
    #if defined(HAVE_OID_ENCODING) && (!defined(HAVE_FIPS) || \
1273
            (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0)))
1274
        wc_ecc_oid_cache_free();
1275
    #endif
1276
0
#endif /* HAVE_ECC */
1277
1278
    #ifdef WC_RNG_HAVE_GLOBAL_FALLBACK_RNG
1279
        (void)wc_RNG_global_fallback_free();
1280
    #endif
1281
1282
    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
1283
        {
1284
            int ret2 = wc_LoggingCleanup();
1285
            if (ret == 0)
1286
                ret = ret2;
1287
        }
1288
    #endif
1289
1290
    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
1291
        ShowMemoryTracker();
1292
    #endif
1293
1294
    #ifdef WOLFSSL_ASYNC_CRYPT
1295
        wolfAsync_HardwareStop();
1296
    #endif
1297
1298
    #ifdef WOLFSSL_RENESAS_TSIP
1299
        tsip_Close();
1300
    #endif
1301
1302
    #if defined(WOLFSSL_RENESAS_RX64_HASH)
1303
        rx64_hw_Close();
1304
    #endif
1305
1306
    #if defined(WOLFSSL_RENESAS_FSPSM)
1307
        wc_fspsm_Close();
1308
    #endif
1309
1310
    #ifdef WOLFSSL_SCE
1311
        WOLFSSL_SCE_GSCE_HANDLE.p_api->close(WOLFSSL_SCE_GSCE_HANDLE.p_ctrl);
1312
    #endif
1313
1314
    #ifdef WOLFSSL_ELS_PKC
1315
        {
1316
            int ret2 = wc_ElsPkc_Cleanup();
1317
            if (ret == 0)
1318
                ret = ret2;
1319
        }
1320
    #endif
1321
    #if defined(WOLFSSL_CAAM)
1322
        wc_caamFree();
1323
    #endif
1324
    #if defined(WOLFSSL_SEC_QORIQ)
1325
        wc_SecQoriqFree();
1326
    #endif
1327
    #if defined(WOLFSSL_TI_AM64X_R5)
1328
        ti_sa2ul_port_cleanup();
1329
    #endif
1330
    /* Unregister before sl_se_deinit(). wc_CryptoCb_Cleanup() further down
1331
     * would also clear the device, but it runs after the SE is torn down, so
1332
     * the unregister command would reach the callback with no SE behind it. */
1333
    #if defined(WOLFSSL_SILABS_CRYPTOCB) && defined(WOLF_CRYPTO_CB)
1334
        {
1335
            int ret2 = wc_SilabsCryptoCb_UnRegisterDevice(WOLFSSL_SILABS_DEVID);
1336
            if (ret == 0)
1337
                ret = ret2;
1338
        }
1339
    #endif
1340
    #ifdef WOLFSSL_SILABS_SE_TYPES
1341
        {
1342
            int ret2 = sl_se_deinit();
1343
            if (ret == 0)
1344
                ret = ret2;
1345
        }
1346
    #endif
1347
    #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT)
1348
        if (wc_se050_get_session() != NULL) {
1349
            int ret2 = wc_se050_close();
1350
1351
            /* A session installed with wc_se050_set_config() is owned by the
1352
             * application and wc_se050_close() deliberately rejects it. */
1353
            if ((ret == 0) && (ret2 != WC_NO_ERR_TRACE(BAD_STATE_E)))
1354
                ret = ret2;
1355
        }
1356
    #endif
1357
    #if defined(WOLFSSL_TROPIC01)
1358
        Tropic01_Deinit();
1359
    #endif
1360
    #if defined(WOLFSSL_RENESAS_TSIP)
1361
        tsip_Close();
1362
    #endif
1363
    #if defined(WOLFSSL_DEVCRYPTO)
1364
        wc_DevCryptoCleanup();
1365
    #endif
1366
    #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
1367
        rpcmem_deinit();
1368
        wolfSSL_CleanupHandle();
1369
    #endif
1370
    #if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && defined(WOLFSSL_LINUXKM)
1371
        wc_linuxkm_free_svr_states();
1372
    #endif
1373
1374
    #ifdef HAVE_ENTROPY_MEMUSE
1375
        Entropy_Final();
1376
    #endif
1377
1378
    #if defined(USE_WINDOWS_API) && defined(WIN_REUSE_CRYPT_HANDLE) && \
1379
        !defined(CUSTOM_RAND_GENERATE_BLOCK)
1380
        wc_WinCryptHandleCleanup();
1381
    #endif
1382
1383
    #if defined(WOLFSSL_MEM_FAIL_COUNT) && defined(WOLFCRYPT_ONLY)
1384
        wc_MemFailCount_Free();
1385
    #endif
1386
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1387
        /* Free the mutex for access to the list of memory locations that
1388
         * must be freed. */
1389
        wc_MemZero_Free();
1390
    #endif
1391
1392
1393
0
        {
1394
0
            int ret2 = wc_local_InitDownDone(&wolfcrypt_init_state);
1395
0
            if (ret == 0)
1396
0
                ret = ret2;
1397
0
        }
1398
1399
0
        return ret;
1400
0
    }
1401
1402
    /* not reached */
1403
0
}
1404
1405
#ifndef NO_FILESYSTEM
1406
1407
/* Helpful function to load file into allocated buffer */
1408
int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen,
1409
    void* heap)
1410
0
{
1411
0
    int ret;
1412
0
    ssize_t fileSz;
1413
0
    XFILE f;
1414
1415
0
    if (fname == NULL || buf == NULL || bufLen == NULL) {
1416
0
        return BAD_FUNC_ARG;
1417
0
    }
1418
1419
    /* set defaults */
1420
0
    *buf = NULL;
1421
0
    *bufLen = 0;
1422
1423
    /* open file (read-only binary) */
1424
0
    f = XFOPEN(fname, "rb");
1425
0
    if (!f) {
1426
0
        WOLFSSL_MSG("wc_LoadFile file load error");
1427
0
        return BAD_PATH_ERROR;
1428
0
    }
1429
1430
0
    if (XFSEEK(f, 0, XSEEK_END) != 0) {
1431
0
        WOLFSSL_MSG("wc_LoadFile file seek error");
1432
0
        XFCLOSE(f);
1433
0
        return BAD_PATH_ERROR;
1434
0
    }
1435
0
    fileSz = XFTELL(f);
1436
0
    if (fileSz < 0) {
1437
0
        WOLFSSL_MSG("wc_LoadFile ftell error");
1438
0
        XFCLOSE(f);
1439
0
        return BAD_PATH_ERROR;
1440
0
    }
1441
0
    if (XFSEEK(f, 0, XSEEK_SET) != 0) {
1442
0
        WOLFSSL_MSG("wc_LoadFile file seek error");
1443
0
        XFCLOSE(f);
1444
0
        return BAD_PATH_ERROR;
1445
0
    }
1446
0
    if (fileSz > 0) {
1447
0
        *bufLen = (size_t)fileSz;
1448
0
        *buf = (byte*)XMALLOC(*bufLen, heap, DYNAMIC_TYPE_TMP_BUFFER);
1449
0
        if (*buf == NULL) {
1450
0
            WOLFSSL_MSG("wc_LoadFile memory error");
1451
0
            ret = MEMORY_E;
1452
0
        }
1453
0
        else {
1454
0
            size_t readLen = XFREAD(*buf, 1, *bufLen, f);
1455
1456
            /* check response code */
1457
0
            ret = (readLen == *bufLen) ? 0 : -1;
1458
0
        }
1459
0
    }
1460
0
    else {
1461
0
        ret = BUFFER_E;
1462
0
    }
1463
0
    XFCLOSE(f);
1464
1465
0
    (void)heap;
1466
1467
0
    return ret;
1468
0
}
1469
1470
#if !defined(NO_WOLFSSL_DIR) && \
1471
    !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
1472
/* File Handling Helper */
1473
/* returns 0 if file exists, WC_ISFILEEXIST_NOFILE if file doesn't exist */
1474
int wc_FileExists(const char* fname)
1475
0
{
1476
0
    struct ReadDirCtx ctx;
1477
1478
0
    XMEMSET(&ctx, 0, sizeof(ctx));
1479
1480
0
    if (fname == NULL)
1481
0
        return 0;
1482
1483
0
    if (XSTAT(fname, &ctx.s) != 0) {
1484
0
         WOLFSSL_MSG("stat on name failed");
1485
0
         return BAD_PATH_ERROR;
1486
0
    } else {
1487
#if defined(USE_WINDOWS_API)
1488
        if (XS_ISREG(ctx.s.st_mode)) {
1489
            return 0;
1490
        }
1491
#elif defined(WOLFSSL_ZEPHYR)
1492
        if (XS_ISREG(ctx.s.type)) {
1493
            return 0;
1494
        }
1495
#elif defined(WOLFSSL_TELIT_M2MB)
1496
        if (XS_ISREG(ctx.s.st_mode)) {
1497
            return 0;
1498
        }
1499
#else
1500
0
        if (XS_ISREG(ctx.s.st_mode)) {
1501
0
            return 0;
1502
0
        }
1503
0
#endif
1504
0
    }
1505
0
    return WC_ISFILEEXIST_NOFILE;
1506
0
}
1507
1508
/* File Handling Helpers */
1509
/* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */
1510
int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name)
1511
0
{
1512
0
    int ret = WC_READDIR_NOFILE; /* default to no files found */
1513
0
    int pathLen = 0;
1514
1515
0
    if (name)
1516
0
        *name = NULL;
1517
1518
0
    if (ctx != NULL)
1519
0
        XMEMSET(ctx, 0, sizeof(ReadDirCtx));
1520
1521
0
    if (ctx == NULL || path == NULL) {
1522
0
        return BAD_FUNC_ARG;
1523
0
    }
1524
1525
0
    pathLen = (int)XSTRLEN(path);
1526
1527
#ifdef USE_WINDOWS_API
1528
    if (pathLen > MAX_FILENAME_SZ - 3)
1529
        return BAD_PATH_ERROR;
1530
1531
    XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3);
1532
    XSTRNCPY(ctx->name + pathLen, "\\*", (size_t)(MAX_FILENAME_SZ - pathLen));
1533
1534
    ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData);
1535
    if (ctx->hFind == INVALID_HANDLE_VALUE) {
1536
        WOLFSSL_MSG("FindFirstFile for path verify locations failed");
1537
        return BAD_PATH_ERROR;
1538
    }
1539
1540
    do {
1541
        if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1542
            int dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName);
1543
1544
            if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
1545
                return BAD_PATH_ERROR;
1546
            }
1547
            XSTRNCPY(ctx->name, path, (size_t)pathLen + 1);
1548
            ctx->name[pathLen] = '\\';
1549
            XSTRNCPY(ctx->name + pathLen + 1,
1550
                     ctx->FindFileData.cFileName,
1551
                     (size_t)(MAX_FILENAME_SZ - pathLen - 1));
1552
            if (name)
1553
                *name = ctx->name;
1554
            return 0;
1555
        }
1556
    } while (FindNextFileA(ctx->hFind, &ctx->FindFileData));
1557
1558
#elif defined(INTIME_RTOS)
1559
    if (pathLen > MAX_FILENAME_SZ - 3)
1560
        return BAD_PATH_ERROR;
1561
1562
    XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3);
1563
    XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen);
1564
1565
    if (!IntimeFindFirst(ctx->name, &ctx->FindFileData)) {
1566
        WOLFSSL_MSG("FindFirstFile for path verify locations failed");
1567
        return BAD_PATH_ERROR;
1568
    }
1569
1570
    do {
1571
        int dnameLen = (int)XSTRLEN(IntimeFilename(ctx));
1572
1573
        if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
1574
            return BAD_PATH_ERROR;
1575
        }
1576
        XSTRNCPY(ctx->name, path, pathLen + 1);
1577
        ctx->name[pathLen] = '\\';
1578
        XSTRNCPY(ctx->name + pathLen + 1,
1579
                 IntimeFilename(ctx),
1580
                 MAX_FILENAME_SZ - pathLen - 1);
1581
        if (0 == wc_FileExists(ctx->name)) {
1582
            if (name)
1583
                *name = ctx->name;
1584
            return 0;
1585
        }
1586
    } while (IntimeFindNext(&ctx->FindFileData));
1587
1588
#elif defined(WOLFSSL_ZEPHYR)
1589
    if (fs_opendir(&ctx->dir, path) != 0) {
1590
        WOLFSSL_MSG("opendir path verify locations failed");
1591
        return BAD_PATH_ERROR;
1592
    }
1593
    ctx->dirp = &ctx->dir;
1594
1595
    while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) {
1596
        int dnameLen = (int)XSTRLEN(ctx->entry.name);
1597
1598
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1599
            ret = BAD_PATH_ERROR;
1600
            break;
1601
        }
1602
        XSTRNCPY(ctx->name, path, pathLen + 1);
1603
        ctx->name[pathLen] = '/';
1604
1605
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1606
         * of earlier check it is known that dnameLen is less than
1607
         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
1608
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1);
1609
        if ((ret = wc_FileExists(ctx->name)) == 0) {
1610
            if (name)
1611
                *name = ctx->name;
1612
            return 0;
1613
        }
1614
    }
1615
#elif defined(WOLFSSL_TELIT_M2MB)
1616
    ctx->dir = m2mb_fs_opendir((const CHAR*)path);
1617
    if (ctx->dir == NULL) {
1618
        WOLFSSL_MSG("opendir path verify locations failed");
1619
        return BAD_PATH_ERROR;
1620
    }
1621
1622
    while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) {
1623
        int dnameLen = (int)XSTRLEN(ctx->entry->d_name);
1624
1625
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1626
            ret = BAD_PATH_ERROR;
1627
            break;
1628
        }
1629
        XSTRNCPY(ctx->name, path, pathLen + 1);
1630
        ctx->name[pathLen] = '/';
1631
1632
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1633
         * of earlier check it is known that dnameLen is less than
1634
         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
1635
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
1636
1637
        if ((ret = wc_FileExists(ctx->name)) == 0) {
1638
            if (name)
1639
                *name = ctx->name;
1640
            return 0;
1641
        }
1642
    }
1643
#else
1644
0
    ctx->dir = opendir(path);
1645
0
    if (ctx->dir == NULL) {
1646
0
        WOLFSSL_MSG("opendir path verify locations failed");
1647
0
        return BAD_PATH_ERROR;
1648
0
    }
1649
1650
0
    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
1651
0
        int dnameLen = (int)XSTRLEN(ctx->entry->d_name);
1652
1653
0
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1654
0
            ret = BAD_PATH_ERROR;
1655
0
            break;
1656
0
        }
1657
0
        XSTRNCPY(ctx->name, path, (size_t)pathLen + 1);
1658
0
        ctx->name[pathLen] = '/';
1659
1660
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1661
         * of earlier check it is known that dnameLen is less than
1662
         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
1663
0
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, (size_t)dnameLen + 1);
1664
0
        if ((ret = wc_FileExists(ctx->name)) == 0) {
1665
0
            if (name)
1666
0
                *name = ctx->name;
1667
0
            return 0;
1668
0
        }
1669
0
    }
1670
0
#endif
1671
0
    wc_ReadDirClose(ctx);
1672
1673
0
    return ret;
1674
0
}
1675
1676
/* returns 0 if file found, WC_READDIR_NOFILE if no more files */
1677
int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name)
1678
0
{
1679
0
    int ret = WC_READDIR_NOFILE; /* default to no file found */
1680
0
    int pathLen = 0;
1681
1682
0
    if (name)
1683
0
        *name = NULL;
1684
1685
0
    if (ctx == NULL || path == NULL) {
1686
0
        return BAD_FUNC_ARG;
1687
0
    }
1688
1689
0
    XMEMSET(ctx->name, 0, MAX_FILENAME_SZ);
1690
0
    pathLen = (int)XSTRLEN(path);
1691
1692
#ifdef USE_WINDOWS_API
1693
    while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) {
1694
        if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1695
            int dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName);
1696
1697
            if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
1698
                return BAD_PATH_ERROR;
1699
            }
1700
            XSTRNCPY(ctx->name, path, (size_t)pathLen + 1);
1701
            ctx->name[pathLen] = '\\';
1702
            XSTRNCPY(ctx->name + pathLen + 1,
1703
                     ctx->FindFileData.cFileName,
1704
                     (size_t)(MAX_FILENAME_SZ - pathLen - 1));
1705
            if (name)
1706
                *name = ctx->name;
1707
            return 0;
1708
        }
1709
    }
1710
1711
#elif defined(INTIME_RTOS)
1712
    while (IntimeFindNext(&ctx->FindFileData)) {
1713
        int dnameLen = (int)XSTRLEN(IntimeFilename(ctx));
1714
1715
        if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
1716
            return BAD_PATH_ERROR;
1717
        }
1718
        XSTRNCPY(ctx->name, path, pathLen + 1);
1719
        ctx->name[pathLen] = '\\';
1720
        XSTRNCPY(ctx->name + pathLen + 1,
1721
                 IntimeFilename(ctx),
1722
                 MAX_FILENAME_SZ - pathLen - 1);
1723
        if (0 == wc_FileExists(ctx->name)) {
1724
            if (name)
1725
                *name = ctx->name;
1726
            return 0;
1727
        }
1728
    }
1729
1730
#elif defined(WOLFSSL_ZEPHYR)
1731
    while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) {
1732
        int dnameLen = (int)XSTRLEN(ctx->entry.name);
1733
1734
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1735
            ret = BAD_PATH_ERROR;
1736
            break;
1737
        }
1738
        XSTRNCPY(ctx->name, path, pathLen + 1);
1739
        ctx->name[pathLen] = '/';
1740
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1741
         * of earlier check it is known that dnameLen is less than
1742
         * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */
1743
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1);
1744
1745
       if ((ret = wc_FileExists(ctx->name)) == 0) {
1746
            if (name)
1747
                *name = ctx->name;
1748
            return 0;
1749
        }
1750
    }
1751
#elif defined(WOLFSSL_TELIT_M2MB)
1752
    while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) {
1753
        int dnameLen = (int)XSTRLEN(ctx->entry->d_name);
1754
1755
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1756
            ret = BAD_PATH_ERROR;
1757
            break;
1758
        }
1759
        XSTRNCPY(ctx->name, path, pathLen + 1);
1760
        ctx->name[pathLen] = '/';
1761
1762
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1763
         * of earlier check it is known that dnameLen is less than
1764
         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
1765
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
1766
1767
        if ((ret = wc_FileExists(ctx->name)) == 0) {
1768
            if (name)
1769
                *name = ctx->name;
1770
            return 0;
1771
        }
1772
    }
1773
#else
1774
0
    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
1775
0
        int dnameLen = (int)XSTRLEN(ctx->entry->d_name);
1776
1777
0
        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
1778
0
            ret = BAD_PATH_ERROR;
1779
0
            break;
1780
0
        }
1781
0
        XSTRNCPY(ctx->name, path, (size_t)pathLen + 1);
1782
0
        ctx->name[pathLen] = '/';
1783
        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
1784
         * of earlier check it is known that dnameLen is less than
1785
         * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */
1786
0
        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, (size_t)dnameLen + 1);
1787
1788
0
        if ((ret = wc_FileExists(ctx->name)) == 0) {
1789
0
            if (name)
1790
0
                *name = ctx->name;
1791
0
            return 0;
1792
0
        }
1793
0
    }
1794
0
#endif
1795
1796
0
    wc_ReadDirClose(ctx);
1797
1798
0
    return ret;
1799
0
}
1800
1801
void wc_ReadDirClose(ReadDirCtx* ctx)
1802
0
{
1803
0
    if (ctx == NULL) {
1804
0
        return;
1805
0
    }
1806
1807
#ifdef USE_WINDOWS_API
1808
    if (ctx->hFind != INVALID_HANDLE_VALUE) {
1809
        FindClose(ctx->hFind);
1810
        ctx->hFind = INVALID_HANDLE_VALUE;
1811
    }
1812
1813
#elif defined(INTIME_RTOS)
1814
    IntimeFindClose(&ctx->FindFileData);
1815
1816
#elif defined(WOLFSSL_ZEPHYR)
1817
    if (ctx->dirp) {
1818
        fs_closedir(ctx->dirp);
1819
        ctx->dirp = NULL;
1820
    }
1821
#elif defined(WOLFSSL_TELIT_M2MB)
1822
    if (ctx->dir) {
1823
        m2mb_fs_closedir(ctx->dir);
1824
        ctx->dir = NULL;
1825
    }
1826
#else
1827
0
    if (ctx->dir) {
1828
0
        if (closedir(ctx->dir) < 0)
1829
0
            WOLFSSL_MSG("closedir() failed");
1830
0
        ctx->dir = NULL;
1831
0
    }
1832
0
#endif
1833
0
}
1834
1835
#endif /* !NO_WOLFSSL_DIR */
1836
#endif /* !NO_FILESYSTEM */
1837
1838
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR)
1839
XFILE z_fs_open(const char* filename, const char* mode)
1840
{
1841
    XFILE file;
1842
    fs_mode_t flags = 0;
1843
1844
    if (mode == NULL)
1845
        return NULL;
1846
1847
    /* Parse mode */
1848
    switch (*mode++) {
1849
        case 'r':
1850
            flags |= FS_O_READ;
1851
            break;
1852
        case 'w':
1853
            flags |= FS_O_WRITE|FS_O_CREATE;
1854
            break;
1855
        case 'a':
1856
            flags |= FS_O_APPEND|FS_O_CREATE;
1857
            break;
1858
        default:
1859
            return NULL;
1860
    }
1861
1862
    /* Ignore binary flag */
1863
    if (*mode == 'b')
1864
        mode++;
1865
    if (*mode == '+') {
1866
        flags |= FS_O_READ;
1867
        /* Don't add write flag if already appending */
1868
        if (!(flags & FS_O_APPEND))
1869
            flags |= FS_O_RDWR;
1870
    }
1871
    /* Ignore binary flag */
1872
    if (*mode == 'b')
1873
        mode++;
1874
    /* Incorrect mode string */
1875
    if (*mode != '\0')
1876
        return NULL;
1877
1878
    file = (XFILE)XMALLOC(sizeof(*file), NULL, DYNAMIC_TYPE_FILE);
1879
    if (file != NULL) {
1880
        fs_file_t_init(file);
1881
        if (fs_open(file, filename, flags) != 0) {
1882
            XFREE(file, NULL, DYNAMIC_TYPE_FILE);
1883
            file = NULL;
1884
        }
1885
    }
1886
1887
    return file;
1888
}
1889
1890
int z_fs_close(XFILE file)
1891
{
1892
    int ret;
1893
1894
    if (file == NULL)
1895
        return -1;
1896
    ret = (fs_close(file) == 0) ? 0 : -1;
1897
1898
    XFREE(file, NULL, DYNAMIC_TYPE_FILE);
1899
1900
    return ret;
1901
}
1902
1903
/* Rewind the file pointer to the beginning of the file */
1904
/* This is not a 'rewind' is not supported in Zephyr so */
1905
/* use fs_seek to move the file pointer to the beginning of the file */
1906
/* calling it z_fs_rewind to avoid future conflicts if rewind is added */
1907
int z_fs_rewind(XFILE file)
1908
{
1909
    return fs_seek(file, 0, FS_SEEK_SET);
1910
}
1911
1912
#endif /* !NO_FILESYSTEM && !WOLFSSL_ZEPHYR */
1913
1914
#if !defined(WOLFSSL_USER_MUTEX)
1915
wolfSSL_Mutex* wc_InitAndAllocMutex(void)
1916
0
{
1917
0
    wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL,
1918
0
            DYNAMIC_TYPE_MUTEX);
1919
0
    if (m != NULL) {
1920
0
        if (wc_InitMutex(m) != 0) {
1921
0
            WOLFSSL_MSG("Init Mutex failed");
1922
0
            XFREE(m, NULL, DYNAMIC_TYPE_MUTEX);
1923
0
            m = NULL;
1924
0
        }
1925
0
    }
1926
0
    else {
1927
0
        WOLFSSL_MSG("Memory error with Mutex allocation");
1928
0
    }
1929
1930
0
    return m;
1931
0
}
1932
#endif
1933
1934
#ifdef USE_WOLF_STRTOK
1935
/* String token (delim) search. If str is null use nextp. */
1936
char* wc_strtok(char *str, const char *delim, char **nextp)
1937
0
{
1938
0
    char* ret;
1939
0
    int i, j;
1940
1941
    /* Use next if str is NULL */
1942
0
    if (str == NULL && nextp)
1943
0
        str = *nextp;
1944
1945
    /* verify str input */
1946
0
    if (str == NULL || *str == '\0')
1947
0
        return NULL;
1948
1949
    /* match on entire delim */
1950
0
    for (i = 0; str[i]; i++) {
1951
0
        for (j = 0; delim[j]; j++) {
1952
0
            if (delim[j] == str[i])
1953
0
                break;
1954
0
        }
1955
0
        if (!delim[j])
1956
0
            break;
1957
0
    }
1958
0
    str += i;
1959
    /* if end of string, not found so return NULL */
1960
0
    if (*str == '\0')
1961
0
        return NULL;
1962
1963
0
    ret = str;
1964
1965
    /* match on first delim */
1966
0
    for (i = 0; str[i]; i++) {
1967
0
        for (j = 0; delim[j]; j++) {
1968
0
            if (delim[j] == str[i])
1969
0
                break;
1970
0
        }
1971
0
        if (delim[j] == str[i])
1972
0
            break;
1973
0
    }
1974
0
    str += i;
1975
1976
    /* null terminate found string */
1977
0
    if (*str)
1978
0
        *str++ = '\0';
1979
1980
    /* return pointer to next */
1981
0
    if (nextp)
1982
0
        *nextp = str;
1983
1984
0
    return ret;
1985
0
}
1986
#endif /* USE_WOLF_STRTOK */
1987
1988
#ifdef USE_WOLF_STRSEP
1989
char* wc_strsep(char **stringp, const char *delim)
1990
0
{
1991
0
    char *s, *tok;
1992
0
    const char *spanp;
1993
1994
    /* null check */
1995
0
    if (stringp == NULL || *stringp == NULL)
1996
0
        return NULL;
1997
1998
0
    s = *stringp;
1999
0
    for (tok = s; *tok; ++tok) {
2000
0
        for (spanp = delim; *spanp; ++spanp) {
2001
            /* found delimiter */
2002
0
            if (*tok == *spanp) {
2003
0
                *tok = '\0'; /* replace delim with null term */
2004
0
                *stringp = tok + 1; /* return past delim */
2005
0
                return s;
2006
0
            }
2007
0
        }
2008
0
    }
2009
2010
0
    *stringp = NULL;
2011
0
    return s;
2012
0
}
2013
#endif /* USE_WOLF_STRSEP */
2014
2015
#ifdef USE_WOLF_STRLCPY
2016
size_t wc_strlcpy(char *dst, const char *src, size_t dstSize)
2017
0
{
2018
0
    size_t i = 0;
2019
2020
0
    if (dstSize != 0) {
2021
        /* Always have to leave a space for NULL */
2022
0
        for (; i < (dstSize - 1) && *src != '\0'; i++) {
2023
0
            *dst++ = *src++;
2024
0
        }
2025
0
        *dst = '\0';
2026
0
    }
2027
2028
    /* strlcpy() returns the length of src, not the number of bytes copied, so
2029
     * that a caller can detect truncation with (ret >= dstSize). Walk whatever
2030
     * did not fit -- src already points at the first byte not copied, and at
2031
     * the whole string when dstSize was 0 (which writes nothing). */
2032
0
    while (*src != '\0') {
2033
0
        i++;
2034
0
        src++;
2035
0
    }
2036
2037
0
    return i; /* length of src, excluding the NULL */
2038
0
}
2039
#endif /* USE_WOLF_STRLCPY */
2040
2041
#ifdef USE_WOLF_STRLCAT
2042
size_t wc_strlcat(char *dst, const char *src, size_t dstSize)
2043
0
{
2044
0
    size_t dstLen = 0;
2045
2046
    /* Find the end of dst without going past dstSize. XSTRLEN() would run off
2047
     * the end of a dst that holds no NUL within dstSize -- the very case this
2048
     * bound exists to contain. */
2049
0
    while (dstLen < dstSize && dst[dstLen] != '\0') {
2050
0
        dstLen++;
2051
0
    }
2052
2053
0
    if (dstLen == dstSize) {
2054
        /* No NUL within dstSize: the length of dst is taken to be dstSize,
2055
         * nothing is appended, and dst is left un-terminated because there is
2056
         * no room for the NUL. Only reachable when dstSize is wrong or dst is
2057
         * not a C string; returning here is what stops the append from running
2058
         * off the end. */
2059
0
        return dstSize + XSTRLEN(src);
2060
0
    }
2061
2062
    /* Total length attempted: the initial length of dst plus the length of
2063
     * src, which is what wc_strlcpy() returns. */
2064
0
    return dstLen + wc_strlcpy(dst + dstLen, src, dstSize - dstLen);
2065
0
}
2066
#endif /* USE_WOLF_STRLCAT */
2067
2068
#ifdef USE_WOLF_STRCASECMP
2069
int wc_strcasecmp(const char *s1, const char *s2)
2070
{
2071
    char c1, c2;
2072
    for (;;++s1, ++s2) {
2073
        c1 = *s1;
2074
        if ((c1 >= 'a') && (c1 <= 'z'))
2075
            c1 = (char)(c1 - ('a' - 'A'));
2076
        c2 = *s2;
2077
        if ((c2 >= 'a') && (c2 <= 'z'))
2078
            c2 = (char)(c2 - ('a' - 'A'));
2079
        if ((c1 != c2) || (c1 == 0))
2080
            break;
2081
    }
2082
    return (c1 - c2);
2083
}
2084
#endif /* USE_WOLF_STRCASECMP */
2085
2086
#ifdef USE_WOLF_STRNCASECMP
2087
int wc_strncasecmp(const char *s1, const char *s2, size_t n)
2088
{
2089
    char c1, c2;
2090
    for (c1 = 0, c2 = 0; n > 0; --n, ++s1, ++s2) {
2091
        c1 = *s1;
2092
        if ((c1 >= 'a') && (c1 <= 'z'))
2093
            c1 = (char)(c1 - ('a' - 'A'));
2094
        c2 = *s2;
2095
        if ((c2 >= 'a') && (c2 <= 'z'))
2096
            c2 = (char)(c2 - ('a' - 'A'));
2097
        if ((c1 != c2) || (c1 == 0))
2098
            break;
2099
    }
2100
    return (c1 - c2);
2101
}
2102
#endif /* USE_WOLF_STRNCASECMP */
2103
2104
#ifdef USE_WOLF_STRDUP
2105
0
char* wc_strdup_ex(const char *src, int memType) {
2106
0
    char *ret = NULL;
2107
0
    word32 len = 0;
2108
2109
0
    if (src) {
2110
0
        len = (word32)XSTRLEN(src) + 1; /* Add one for null terminator */
2111
0
        ret = (char*)XMALLOC(len, NULL, memType);
2112
0
        if (ret != NULL) {
2113
0
            XMEMCPY(ret, src, len);
2114
0
        }
2115
0
    }
2116
2117
0
    return ret;
2118
0
}
2119
#endif
2120
2121
#ifdef WOLFSSL_WIDE_BYTE
2122
2123
/* Packed octet stream -> one octet per byte cell.  See WC_OCTETS_PER_BYTE in
2124
 * types.h.  in holds the packed stream, low octet of a cell first, and must not
2125
 * overlap out.  Returns 0, BAD_FUNC_ARG on NULL, BUFFER_E if either buffer is
2126
 * short. */
2127
int wc_UnpackOctets(byte* out, word32 outSz, const byte* in, word32 inSz,
2128
    word32 octetSz)
2129
{
2130
    word32 i;
2131
2132
    if ((out == NULL) || (in == NULL)) {
2133
        return BAD_FUNC_ARG;
2134
    }
2135
    if ((outSz < octetSz) || (inSz < WC_PACKED_CELLS(octetSz))) {
2136
        return BUFFER_E;
2137
    }
2138
2139
    for (i = 0; i < octetSz; i++) {
2140
        out[i] = WC_OCTET((word32)in[i / WC_OCTETS_PER_BYTE] >>
2141
            ((i % WC_OCTETS_PER_BYTE) * 8));
2142
    }
2143
2144
    return 0;
2145
}
2146
2147
/* Inverse of wc_UnpackOctets(), for flash or a byte-oriented peripheral.  in
2148
 * holds one octet per cell and must not overlap out. */
2149
int wc_PackOctets(byte* out, word32 outSz, const byte* in, word32 inSz,
2150
    word32 octetSz)
2151
{
2152
    word32 i;
2153
2154
    if ((out == NULL) || (in == NULL)) {
2155
        return BAD_FUNC_ARG;
2156
    }
2157
    if ((outSz < WC_PACKED_CELLS(octetSz)) || (inSz < octetSz)) {
2158
        return BUFFER_E;
2159
    }
2160
2161
    XMEMSET(out, 0, WC_PACKED_CELLS(octetSz));   /* zero-fill partial tail */
2162
    for (i = 0; i < octetSz; i++) {
2163
        out[i / WC_OCTETS_PER_BYTE] |= (byte)((word32)WC_OCTET(in[i]) <<
2164
            ((i % WC_OCTETS_PER_BYTE) * 8));
2165
    }
2166
2167
    return 0;
2168
}
2169
2170
#endif /* WOLFSSL_WIDE_BYTE */
2171
2172
#ifdef WOLFSSL_ATOMIC_OPS
2173
2174
#if defined(WOLFSSL_USER_DEFINED_ATOMICS)
2175
2176
#elif defined(SINGLE_THREADED)
2177
2178
#elif defined(WOLFSSL_BSDKM)
2179
/* Note: using compiler built-ins like __atomic_fetch_add will technically
2180
 * build in FreeBSD kernel, but are not commonly used in FreeBSD kernel and
2181
 * might not be safe or portable.
2182
 * */
2183
void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, WC_ATOMIC_INT_ARG i)
2184
{
2185
    *c = i;
2186
}
2187
2188
void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG i)
2189
{
2190
    *c = i;
2191
}
2192
2193
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c,
2194
                                              WC_ATOMIC_INT_ARG i)
2195
{
2196
    return atomic_fetchadd_int(c, i);
2197
}
2198
2199
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c,
2200
                                              WC_ATOMIC_INT_ARG i)
2201
{
2202
    return atomic_fetchadd_int(c, -i);
2203
}
2204
2205
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c,
2206
                                              WC_ATOMIC_INT_ARG i)
2207
{
2208
    int val = atomic_fetchadd_int(c, i);
2209
    return val + i;
2210
}
2211
2212
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c,
2213
                                              WC_ATOMIC_INT_ARG i)
2214
{
2215
    int val = atomic_fetchadd_int(c, -i);
2216
    return val - i;
2217
}
2218
2219
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c,
2220
                                                WC_ATOMIC_UINT_ARG i)
2221
{
2222
    return atomic_fetchadd_int(c, i);
2223
}
2224
2225
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c,
2226
                                                WC_ATOMIC_UINT_ARG i)
2227
{
2228
    return atomic_fetchadd_int(c, -i);
2229
}
2230
2231
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c,
2232
                                                WC_ATOMIC_UINT_ARG i)
2233
{
2234
    WC_ATOMIC_UINT_ARG val = atomic_fetchadd_int(c, i);
2235
    return val + i;
2236
}
2237
2238
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c,
2239
                                                WC_ATOMIC_UINT_ARG i)
2240
{
2241
    unsigned int val = atomic_fetchadd_int(c, -i);
2242
    return val - i;
2243
}
2244
2245
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c,
2246
                                              WC_ATOMIC_INT_ARG new_i)
2247
{
2248
    return atomic_swap_int(c, new_i);
2249
}
2250
2251
int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c,
2252
                                       WC_ATOMIC_INT_ARG *expected_i,
2253
                                       WC_ATOMIC_INT_ARG new_i)
2254
{
2255
    u_int exp = (u_int) *expected_i;
2256
    int ret = atomic_fcmpset_int(c, &exp, new_i);
2257
    *expected_i = (int)exp;
2258
    return ret;
2259
}
2260
2261
int wolfSSL_Atomic_Uint_CompareExchange(
2262
    wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG *expected_i,
2263
    WC_ATOMIC_UINT_ARG new_i)
2264
{
2265
    u_int exp = (u_int)*expected_i;
2266
    int ret = atomic_fcmpset_int(c, &exp, new_i);
2267
    *expected_i = (unsigned int)exp;
2268
    return ret;
2269
}
2270
2271
int wolfSSL_Atomic_Ptr_CompareExchange(
2272
    void * volatile *c, void **expected_ptr, void *new_ptr)
2273
{
2274
    uintptr_t exp = (uintptr_t)*expected_ptr;
2275
    int ret = atomic_fcmpset_ptr((uintptr_t *)c, &exp, (uintptr_t)new_ptr);
2276
    *expected_ptr = (void *)exp;
2277
    return ret;
2278
}
2279
2280
#elif defined(HAVE_C___ATOMIC) && defined(WOLFSSL_HAVE_ATOMIC_H) && \
2281
      !defined(__cplusplus) && !defined(NO_STDATOMIC_H)
2282
2283
/* Default C Implementation */
2284
void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, WC_ATOMIC_INT_ARG i)
2285
0
{
2286
0
    atomic_init(c, i);
2287
0
}
2288
2289
void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG i)
2290
0
{
2291
0
    atomic_init(c, i);
2292
0
}
2293
2294
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c,
2295
                                              WC_ATOMIC_INT_ARG i)
2296
0
{
2297
0
    return atomic_fetch_add_explicit(c, i, memory_order_relaxed);
2298
0
}
2299
2300
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c,
2301
                                              WC_ATOMIC_INT_ARG i)
2302
0
{
2303
0
    return atomic_fetch_sub_explicit(c, i, memory_order_relaxed);
2304
0
}
2305
2306
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c,
2307
                                              WC_ATOMIC_INT_ARG i)
2308
0
{
2309
0
    WC_ATOMIC_INT_ARG ret =
2310
0
        atomic_fetch_add_explicit(c, i, memory_order_relaxed);
2311
0
    return ret + i;
2312
0
}
2313
2314
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c,
2315
                                              WC_ATOMIC_INT_ARG i)
2316
0
{
2317
0
    WC_ATOMIC_INT_ARG ret =
2318
0
        atomic_fetch_sub_explicit(c, i, memory_order_relaxed);
2319
0
    return ret - i;
2320
0
}
2321
2322
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c,
2323
                                              WC_ATOMIC_INT_ARG new_i)
2324
0
{
2325
0
    return atomic_exchange_explicit(c, new_i, memory_order_seq_cst);
2326
0
}
2327
2328
int wolfSSL_Atomic_Int_CompareExchange(
2329
    wolfSSL_Atomic_Int* c, WC_ATOMIC_INT_ARG *expected_i,
2330
    WC_ATOMIC_INT_ARG new_i)
2331
0
{
2332
    /* For the success path, use full synchronization with barriers --
2333
     * "Sequentially-consistent ordering" -- so that all threads see the same
2334
     * "single total modification order of all atomic operations" -- but on
2335
     * failure we just need to be sure we acquire the value that changed out
2336
     * from under us.
2337
     */
2338
0
    return atomic_compare_exchange_strong_explicit(
2339
0
        c, expected_i, new_i, memory_order_seq_cst, memory_order_acquire);
2340
0
}
2341
2342
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c,
2343
                                                WC_ATOMIC_UINT_ARG i)
2344
0
{
2345
0
    return atomic_fetch_add_explicit(c, i, memory_order_relaxed);
2346
0
}
2347
2348
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c,
2349
                                                WC_ATOMIC_UINT_ARG i)
2350
0
{
2351
0
    return atomic_fetch_sub_explicit(c, i, memory_order_relaxed);
2352
0
}
2353
2354
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c,
2355
                                                WC_ATOMIC_UINT_ARG i)
2356
0
{
2357
0
    WC_ATOMIC_UINT_ARG ret =
2358
0
        atomic_fetch_add_explicit(c, i, memory_order_relaxed);
2359
0
    return ret + i;
2360
0
}
2361
2362
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c,
2363
                                                WC_ATOMIC_UINT_ARG i)
2364
0
{
2365
0
    WC_ATOMIC_UINT_ARG ret =
2366
0
        atomic_fetch_sub_explicit(c, i, memory_order_relaxed);
2367
0
    return ret - i;
2368
0
}
2369
2370
int wolfSSL_Atomic_Uint_CompareExchange(
2371
    wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG *expected_i,
2372
    WC_ATOMIC_UINT_ARG new_i)
2373
1
{
2374
    /* For the success path, use full synchronization with barriers --
2375
     * "Sequentially-consistent ordering" -- so that all threads see the same
2376
     * "single total modification order of all atomic operations" -- but on
2377
     * failure we just need to be sure we acquire the value that changed out
2378
     * from under us.
2379
     */
2380
1
    return atomic_compare_exchange_strong_explicit(
2381
1
        c, expected_i, new_i, memory_order_seq_cst, memory_order_acquire);
2382
1
}
2383
2384
int wolfSSL_Atomic_Ptr_CompareExchange(
2385
    void * volatile *c, void **expected_ptr, void *new_ptr)
2386
0
{
2387
    /* use gcc-built-in __atomic_compare_exchange_n(), not
2388
     * atomic_compare_exchange_strong_explicit(), to sidestep _Atomic type
2389
     * requirements.
2390
     */
2391
0
     if (__atomic_compare_exchange_n(
2392
0
             c, expected_ptr, new_ptr,
2393
#ifdef WOLF_C89
2394
             0 /* weak */,
2395
#else
2396
0
             (_Bool)0 /* weak */,
2397
0
#endif
2398
0
             __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))
2399
0
         return 1;
2400
0
     else
2401
0
         return 0;
2402
0
}
2403
2404
#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED)
2405
/* direct calls using gcc-style compiler built-ins */
2406
2407
void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, WC_ATOMIC_INT_ARG i)
2408
{
2409
    *c = i;
2410
}
2411
2412
void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG i)
2413
{
2414
    *c = i;
2415
}
2416
2417
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c,
2418
                                              WC_ATOMIC_INT_ARG i)
2419
{
2420
    return __atomic_fetch_add(c, i, __ATOMIC_RELAXED);
2421
}
2422
2423
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c,
2424
                                              WC_ATOMIC_INT_ARG i)
2425
{
2426
    return __atomic_fetch_sub(c, i, __ATOMIC_RELAXED);
2427
}
2428
2429
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c,
2430
                                              WC_ATOMIC_INT_ARG i)
2431
{
2432
    return __atomic_add_fetch(c, i, __ATOMIC_RELAXED);
2433
}
2434
2435
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c,
2436
                                              WC_ATOMIC_INT_ARG i)
2437
{
2438
    return __atomic_sub_fetch(c, i, __ATOMIC_RELAXED);
2439
}
2440
2441
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c,
2442
                                              WC_ATOMIC_INT_ARG new_i)
2443
{
2444
    return __atomic_exchange_n(c, new_i, __ATOMIC_SEQ_CST);
2445
}
2446
2447
int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c,
2448
                                       WC_ATOMIC_INT_ARG *expected_i,
2449
                                       WC_ATOMIC_INT_ARG new_i)
2450
{
2451
    /* For the success path, use full synchronization with barriers --
2452
     * "Sequentially-consistent ordering" -- so that all threads see the same
2453
     * "single total modification order of all atomic operations" -- but on
2454
     * failure we just need to be sure we acquire the value that changed out
2455
     * from under us.
2456
     */
2457
    return __atomic_compare_exchange_n(c, expected_i, new_i, 0 /* weak */,
2458
                                       __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
2459
}
2460
2461
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c,
2462
                                                WC_ATOMIC_UINT_ARG i)
2463
{
2464
    return __atomic_fetch_add(c, i, __ATOMIC_RELAXED);
2465
}
2466
2467
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c,
2468
                                                WC_ATOMIC_UINT_ARG i)
2469
{
2470
    return __atomic_fetch_sub(c, i, __ATOMIC_RELAXED);
2471
}
2472
2473
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c,
2474
                                                WC_ATOMIC_UINT_ARG i)
2475
{
2476
    return __atomic_add_fetch(c, i, __ATOMIC_RELAXED);
2477
}
2478
2479
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c,
2480
                                                WC_ATOMIC_UINT_ARG i)
2481
{
2482
    return __atomic_sub_fetch(c, i, __ATOMIC_RELAXED);
2483
}
2484
2485
int wolfSSL_Atomic_Uint_CompareExchange(
2486
    wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG *expected_i,
2487
    WC_ATOMIC_UINT_ARG new_i)
2488
{
2489
    /* For the success path, use full synchronization with barriers --
2490
     * "Sequentially-consistent ordering" -- so that all threads see the same
2491
     * "single total modification order of all atomic operations" -- but on
2492
     * failure we just need to be sure we acquire the value that changed out
2493
     * from under us.
2494
     */
2495
    return __atomic_compare_exchange_n(
2496
        c, expected_i, new_i, 0 /* weak */, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
2497
}
2498
2499
int wolfSSL_Atomic_Ptr_CompareExchange(
2500
    void * volatile *c, void **expected_ptr, void *new_ptr)
2501
{
2502
    return __atomic_compare_exchange_n(
2503
        c, expected_ptr, new_ptr, 0 /* weak */,
2504
        __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
2505
}
2506
2507
#elif defined(_MSC_VER) && !defined(WOLFSSL_NOT_WINDOWS_API)
2508
2509
void wolfSSL_Atomic_Int_Init(wolfSSL_Atomic_Int* c, WC_ATOMIC_INT_ARG i)
2510
{
2511
    *c = i;
2512
}
2513
2514
void wolfSSL_Atomic_Uint_Init(wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG i)
2515
{
2516
    *c = i;
2517
}
2518
2519
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchAdd(wolfSSL_Atomic_Int* c,
2520
                                              WC_ATOMIC_INT_ARG i)
2521
{
2522
    return (int)_InterlockedExchangeAdd(c, (long)i);
2523
}
2524
2525
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_FetchSub(wolfSSL_Atomic_Int* c,
2526
                                              WC_ATOMIC_INT_ARG i)
2527
{
2528
    return (int)_InterlockedExchangeAdd(c, (long)-i);
2529
}
2530
2531
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_AddFetch(wolfSSL_Atomic_Int* c,
2532
                                              WC_ATOMIC_INT_ARG i)
2533
{
2534
    WC_ATOMIC_INT_ARG ret =
2535
        (WC_ATOMIC_INT_ARG)_InterlockedExchangeAdd(c, (long)i);
2536
    return ret + i;
2537
}
2538
2539
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_SubFetch(wolfSSL_Atomic_Int* c,
2540
                                              WC_ATOMIC_INT_ARG i)
2541
{
2542
    WC_ATOMIC_INT_ARG ret =
2543
        (WC_ATOMIC_INT_ARG)_InterlockedExchangeAdd(c, (long)-i);
2544
    return ret - i;
2545
}
2546
2547
WC_ATOMIC_INT_ARG wolfSSL_Atomic_Int_Exchange(wolfSSL_Atomic_Int* c,
2548
                                              WC_ATOMIC_INT_ARG new_i)
2549
{
2550
    long actual_i = InterlockedExchange(c, (long)new_i);
2551
    return (WC_ATOMIC_INT_ARG)actual_i;
2552
}
2553
2554
int wolfSSL_Atomic_Int_CompareExchange(wolfSSL_Atomic_Int* c,
2555
                                       WC_ATOMIC_INT_ARG *expected_i,
2556
                                       WC_ATOMIC_INT_ARG new_i)
2557
{
2558
    long actual_i = InterlockedCompareExchange(c, (long)new_i,
2559
                                               (long)*expected_i);
2560
    if (actual_i == (long)*expected_i) {
2561
        return 1;
2562
    }
2563
    else {
2564
        *expected_i = (WC_ATOMIC_INT_ARG)actual_i;
2565
        return 0;
2566
    }
2567
}
2568
2569
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchAdd(wolfSSL_Atomic_Uint* c,
2570
                                                WC_ATOMIC_UINT_ARG i)
2571
{
2572
    return (WC_ATOMIC_UINT_ARG)_InterlockedExchangeAdd((wolfSSL_Atomic_Int *)c,
2573
                                                       (long)i);
2574
}
2575
2576
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_FetchSub(wolfSSL_Atomic_Uint* c,
2577
                                                WC_ATOMIC_UINT_ARG i)
2578
{
2579
    return (WC_ATOMIC_UINT_ARG)_InterlockedExchangeAdd((wolfSSL_Atomic_Int *)c,
2580
                                                       -(long)i);
2581
}
2582
2583
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_AddFetch(wolfSSL_Atomic_Uint* c,
2584
                                                WC_ATOMIC_UINT_ARG i)
2585
{
2586
    WC_ATOMIC_UINT_ARG ret = (WC_ATOMIC_UINT_ARG)_InterlockedExchangeAdd
2587
        ((wolfSSL_Atomic_Int *)c, (long)i);
2588
    return ret + i;
2589
}
2590
2591
WC_ATOMIC_UINT_ARG wolfSSL_Atomic_Uint_SubFetch(wolfSSL_Atomic_Uint* c,
2592
                                                WC_ATOMIC_UINT_ARG i)
2593
{
2594
    WC_ATOMIC_UINT_ARG ret = (WC_ATOMIC_UINT_ARG)_InterlockedExchangeAdd
2595
        ((wolfSSL_Atomic_Int *)c, -(long)i);
2596
    return ret - i;
2597
}
2598
2599
int wolfSSL_Atomic_Uint_CompareExchange(
2600
    wolfSSL_Atomic_Uint* c, WC_ATOMIC_UINT_ARG *expected_i,
2601
    WC_ATOMIC_UINT_ARG new_i)
2602
{
2603
    long actual_i = InterlockedCompareExchange(
2604
        (wolfSSL_Atomic_Int *)c, (long)new_i, (long)*expected_i);
2605
    if (actual_i == (long)*expected_i) {
2606
        return 1;
2607
    }
2608
    else {
2609
        *expected_i = (WC_ATOMIC_UINT_ARG)actual_i;
2610
        return 0;
2611
    }
2612
}
2613
2614
int wolfSSL_Atomic_Ptr_CompareExchange(
2615
    void * volatile * c, void **expected_ptr, void *new_ptr)
2616
{
2617
#ifdef _WIN64
2618
    LONG64 actual_ptr = InterlockedCompareExchange64(
2619
        (LONG64 *)c, (LONG64)new_ptr, (LONG64)*expected_ptr);
2620
    if (actual_ptr == (LONG64)*expected_ptr) {
2621
        return 1;
2622
    }
2623
    else {
2624
        *expected_ptr = (void *)actual_ptr;
2625
        return 0;
2626
    }
2627
#else /* !_WIN64 */
2628
    LONG actual_ptr = InterlockedCompareExchange(
2629
        (LONG *)c, (LONG)new_ptr, (LONG)*expected_ptr);
2630
    if (actual_ptr == (LONG)*expected_ptr) {
2631
        return 1;
2632
    }
2633
    else {
2634
        *expected_ptr = (void *)actual_ptr;
2635
        return 0;
2636
    }
2637
#endif /* !_WIN64 */
2638
}
2639
2640
#endif
2641
2642
#endif /* WOLFSSL_ATOMIC_OPS */
2643
2644
/* Make sure the pointer size assumptions of
2645
 * wolfSSL_Atomic_Func_Ptr_CompareExchange() are met. */
2646
#ifdef wolfSSL_Atomic_Func_Ptr_CompareExchange
2647
    wc_static_assert(sizeof(void (*)(void)) == sizeof(void *));
2648
#endif
2649
2650
#if !defined(SINGLE_THREADED)
2651
2652
void wolfSSL_RefWithMutexInit(wolfSSL_RefWithMutex* ref, int* err)
2653
0
{
2654
0
    int ret = wc_InitMutex(&ref->mutex);
2655
0
    if (ret != 0) {
2656
0
        WOLFSSL_MSG("Failed to create mutex for reference counting!");
2657
0
    }
2658
0
    ref->count = 1;
2659
2660
0
    *err = ret;
2661
0
}
2662
2663
void wolfSSL_RefWithMutexFree(wolfSSL_RefWithMutex* ref)
2664
0
{
2665
0
    if (wc_FreeMutex(&ref->mutex) != 0) {
2666
0
        WOLFSSL_MSG("Failed to free mutex of reference counting!");
2667
0
    }
2668
0
    ref->count = 0;
2669
0
}
2670
2671
void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref, int* err)
2672
0
{
2673
0
    int ret = wc_LockMutex(&ref->mutex);
2674
0
    if (ret != 0) {
2675
0
        WOLFSSL_MSG("Failed to lock mutex for reference increment!");
2676
0
    }
2677
0
    else {
2678
0
        ref->count++;
2679
0
        wc_UnLockMutex(&ref->mutex);
2680
0
    }
2681
0
    *err = ret;
2682
0
}
2683
2684
void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref, int *new_count,
2685
                              int* err)
2686
0
{
2687
0
    int ret = wc_LockMutex(&ref->mutex);
2688
0
    if (ret != 0) {
2689
0
        WOLFSSL_MSG("Failed to lock mutex for reference increment!");
2690
0
        *new_count = -1;
2691
0
    }
2692
0
    else {
2693
0
        *new_count = ++ref->count;
2694
0
        wc_UnLockMutex(&ref->mutex);
2695
0
    }
2696
0
    *err = ret;
2697
0
}
2698
2699
void wolfSSL_RefWithMutexInc_IfAtLeast(wolfSSL_RefWithMutex* ref,
2700
                                       int cur_at_least, int *new_count,
2701
                                       int* err)
2702
0
{
2703
0
    *err = wc_LockMutex(&ref->mutex);
2704
0
    if (*err != 0) {
2705
0
        WOLFSSL_MSG("Failed to lock mutex for reference increment!");
2706
0
        *new_count = -1;
2707
0
    }
2708
0
    else {
2709
0
        if (ref->count < cur_at_least) {
2710
0
            *new_count = ref->count;
2711
0
            *err = BAD_STATE_E;
2712
0
        }
2713
0
        else {
2714
0
            *new_count = ++ref->count;
2715
0
            *err = 0;
2716
0
        }
2717
0
        wc_UnLockMutex(&ref->mutex);
2718
0
    }
2719
0
}
2720
2721
int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref)
2722
0
{
2723
0
    return wc_LockMutex(&ref->mutex);
2724
0
}
2725
2726
int wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref)
2727
0
{
2728
0
    return wc_UnLockMutex(&ref->mutex);
2729
0
}
2730
2731
void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref, int* isZero, int* err)
2732
0
{
2733
0
    int ret = wc_LockMutex(&ref->mutex);
2734
0
    if (ret != 0) {
2735
0
        WOLFSSL_MSG("Failed to lock mutex for reference decrement!");
2736
        /* Can't say count is zero. */
2737
0
        *isZero = 0;
2738
0
    }
2739
0
    else {
2740
0
        if (ref->count > 0) {
2741
0
            ref->count--;
2742
0
        }
2743
0
        *isZero = (ref->count == 0);
2744
0
        wc_UnLockMutex(&ref->mutex);
2745
0
    }
2746
0
    *err = ret;
2747
0
}
2748
2749
void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref, int* new_count,
2750
                              int* err)
2751
0
{
2752
0
    int ret = wc_LockMutex(&ref->mutex);
2753
0
    if (ret != 0) {
2754
0
        WOLFSSL_MSG("Failed to lock mutex for reference decrement!");
2755
0
        *new_count = -1;
2756
0
    }
2757
0
    else {
2758
0
        if (ref->count > 0) {
2759
0
            ref->count--;
2760
0
        }
2761
0
        *new_count = ref->count;
2762
0
        wc_UnLockMutex(&ref->mutex);
2763
0
    }
2764
0
    *err = ret;
2765
0
}
2766
2767
void wolfSSL_RefWithMutexDec_IfEquals(wolfSSL_RefWithMutex* ref,
2768
                                      int current_count, int* new_count,
2769
                                      int* err)
2770
0
{
2771
0
    *err = wc_LockMutex(&ref->mutex);
2772
0
    if (*err != 0) {
2773
0
        WOLFSSL_MSG("Failed to lock mutex for reference decrement!");
2774
0
        *new_count = -1;
2775
0
    }
2776
0
    else {
2777
0
        if (ref->count != current_count) {
2778
0
            *new_count = ref->count;
2779
0
            *err = BAD_STATE_E;
2780
0
        }
2781
0
        else {
2782
0
            *new_count = --ref->count;
2783
0
            *err = 0;
2784
0
        }
2785
0
        wc_UnLockMutex(&ref->mutex);
2786
0
    }
2787
0
}
2788
2789
#endif /* ! SINGLE_THREADED */
2790
2791
#if WOLFSSL_CRYPT_HW_MUTEX
2792
/* Mutex for protection of cryptography hardware */
2793
static wolfSSL_Mutex wcCryptHwMutex
2794
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwMutex);
2795
#ifndef WOLFSSL_MUTEX_INITIALIZER
2796
static int wcCryptHwMutexInit = 0;
2797
#endif
2798
2799
int wolfSSL_CryptHwMutexInit(void)
2800
{
2801
    int ret = 0;
2802
#ifndef WOLFSSL_MUTEX_INITIALIZER
2803
    if (wcCryptHwMutexInit == 0) {
2804
        ret = wc_InitMutex(&wcCryptHwMutex);
2805
        if (ret == 0) {
2806
            wcCryptHwMutexInit = 1;
2807
        }
2808
    }
2809
#endif
2810
    return ret;
2811
}
2812
int wolfSSL_CryptHwMutexLock(void)
2813
{
2814
    /* Make sure HW Mutex has been initialized */
2815
    int ret = wolfSSL_CryptHwMutexInit();
2816
    if (ret == 0) {
2817
        ret = wc_LockMutex(&wcCryptHwMutex);
2818
    }
2819
    return ret;
2820
}
2821
int wolfSSL_CryptHwMutexUnLock(void)
2822
{
2823
#ifndef WOLFSSL_MUTEX_INITIALIZER
2824
    if (wcCryptHwMutexInit) {
2825
        return wc_UnLockMutex(&wcCryptHwMutex);
2826
    }
2827
    else {
2828
        return BAD_MUTEX_E;
2829
    }
2830
#else
2831
    /* statically initialized (no runtime init flag) -- always valid to unlock */
2832
    return wc_UnLockMutex(&wcCryptHwMutex);
2833
#endif
2834
}
2835
#endif /* WOLFSSL_CRYPT_HW_MUTEX */
2836
2837
2838
#if WOLFSSL_CRYPT_HW_MUTEX && defined(WOLFSSL_ALGO_HW_MUTEX)
2839
/* Mutex for protection of cryptography hardware */
2840
#ifndef NO_RNG_MUTEX
2841
static wolfSSL_Mutex wcCryptHwRngMutex
2842
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwRngMutex);
2843
#endif /* NO_RNG_MUTEX */
2844
#ifndef NO_AES_MUTEX
2845
static wolfSSL_Mutex wcCryptHwAesMutex
2846
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwAesMutex);
2847
#endif /* NO_AES_MUTEX */
2848
#ifndef NO_HASH_MUTEX
2849
static wolfSSL_Mutex wcCryptHwHashMutex
2850
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwHashMutex);
2851
#endif /* NO_HASH_MUTEX */
2852
#ifndef NO_PK_MUTEX
2853
static wolfSSL_Mutex wcCryptHwPkMutex
2854
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wcCryptHwPkMutex);
2855
#endif /* NO_PK_MUTEX */
2856
2857
#ifndef WOLFSSL_MUTEX_INITIALIZER
2858
#ifndef NO_RNG_MUTEX
2859
static int wcCryptHwRngMutexInit = 0;
2860
#endif /* NO_RNG_MUTEX */
2861
#ifndef NO_AES_MUTEX
2862
static int wcCryptHwAesMutexInit = 0;
2863
#endif /* NO_AES_MUTEX */
2864
#ifndef NO_HASH_MUTEX
2865
static int wcCryptHwHashMutexInit = 0;
2866
#endif /* NO_HASH_MUTEX */
2867
#ifndef NO_PK_MUTEX
2868
static int wcCryptHwPkMutexInit = 0;
2869
#endif /* NO_PK_MUTEX */
2870
#endif /* WOLFSSL_MUTEX_INITIALIZER */
2871
2872
2873
/* Allows ability to switch to different mutex based on enum type */
2874
/* hw_mutex_algo, expects the dereferenced Ptrs to be set to NULL */
2875
static int hwAlgoPtrSet(hw_mutex_algo hwAlgo, wolfSSL_Mutex** wcHwAlgoMutexPtr,
2876
                                int** wcHwAlgoInitPtr)
2877
{
2878
    if (*wcHwAlgoMutexPtr != NULL || *wcHwAlgoInitPtr != NULL) {
2879
        return BAD_FUNC_ARG;
2880
    }
2881
    switch (hwAlgo) {
2882
        #ifndef NO_RNG_MUTEX
2883
        case rng_mutex:
2884
            *wcHwAlgoMutexPtr = &wcCryptHwRngMutex;
2885
            *wcHwAlgoInitPtr = &wcCryptHwRngMutexInit;
2886
            break;
2887
        #endif
2888
        #ifndef NO_AES_MUTEX
2889
        case aes_mutex:
2890
            *wcHwAlgoMutexPtr = &wcCryptHwAesMutex;
2891
            *wcHwAlgoInitPtr = &wcCryptHwAesMutexInit;
2892
            break;
2893
        #endif
2894
        #ifndef NO_HASH_MUTEX
2895
        case hash_mutex:
2896
            *wcHwAlgoMutexPtr = &wcCryptHwHashMutex;
2897
            *wcHwAlgoInitPtr = &wcCryptHwHashMutexInit;
2898
            break;
2899
        #endif
2900
        #ifndef NO_PK_MUTEX
2901
        case pk_mutex:
2902
            *wcHwAlgoMutexPtr = &wcCryptHwPkMutex;
2903
            *wcHwAlgoInitPtr = &wcCryptHwPkMutexInit;
2904
            break;
2905
        #endif
2906
        default:
2907
            return BAD_FUNC_ARG;
2908
    }
2909
    return 0;
2910
}
2911
2912
static int hwAlgoMutexInit(hw_mutex_algo hwAlgo)
2913
{
2914
    int ret = 0;
2915
#ifndef WOLFSSL_MUTEX_INITIALIZER
2916
    wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL;
2917
    int* wcHwAlgoInitPtr = NULL;
2918
    ret = hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr);
2919
    if (ret != 0) {
2920
        return ret;
2921
    }
2922
    if (*wcHwAlgoInitPtr == 0) {
2923
        ret = wc_InitMutex(wcHwAlgoMutexPtr);
2924
        if (ret == 0) {
2925
            *wcHwAlgoInitPtr = 1;
2926
        }
2927
    }
2928
#endif
2929
    return ret;
2930
}
2931
2932
static int hwAlgoMutexLock(hw_mutex_algo hwAlgo)
2933
{
2934
    /* Make sure HW Mutex has been initialized */
2935
    int ret = 0;
2936
    wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL;
2937
    int* wcHwAlgoInitPtr = NULL;
2938
    ret = hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr);
2939
    if (ret != 0) {
2940
        return ret;
2941
    }
2942
    ret = hwAlgoMutexInit(hwAlgo);
2943
    if (ret == 0) {
2944
        ret = wc_LockMutex(wcHwAlgoMutexPtr);
2945
    }
2946
    return ret;
2947
}
2948
2949
static int hwAlgoMutexUnLock(hw_mutex_algo hwAlgo)
2950
{
2951
    wolfSSL_Mutex* wcHwAlgoMutexPtr = NULL;
2952
    int* wcHwAlgoInitPtr = NULL;
2953
    if (hwAlgoPtrSet(hwAlgo, &wcHwAlgoMutexPtr, &wcHwAlgoInitPtr) != 0) {
2954
        return BAD_FUNC_ARG;
2955
    }
2956
    if (*wcHwAlgoInitPtr) {
2957
        return wc_UnLockMutex(wcHwAlgoMutexPtr);
2958
    }
2959
    else {
2960
        return BAD_MUTEX_E;
2961
    }
2962
}
2963
2964
/* Wrap around generic hwAlgo* functions and use correct */
2965
/* global mutex to determine if it can be unlocked/locked */
2966
#ifndef NO_RNG_MUTEX
2967
int wolfSSL_HwRngMutexInit(void)
2968
{
2969
    return hwAlgoMutexInit(rng_mutex);
2970
}
2971
int wolfSSL_HwRngMutexLock(void)
2972
{
2973
    return hwAlgoMutexLock(rng_mutex);
2974
}
2975
int wolfSSL_HwRngMutexUnLock(void)
2976
{
2977
    return hwAlgoMutexUnLock(rng_mutex);
2978
}
2979
#endif /* NO_RNG_MUTEX */
2980
2981
#ifndef NO_AES_MUTEX
2982
int wolfSSL_HwAesMutexInit(void)
2983
{
2984
    return hwAlgoMutexInit(aes_mutex);
2985
}
2986
int wolfSSL_HwAesMutexLock(void)
2987
{
2988
    return hwAlgoMutexLock(aes_mutex);
2989
}
2990
int wolfSSL_HwAesMutexUnLock(void)
2991
{
2992
    return hwAlgoMutexUnLock(aes_mutex);
2993
}
2994
#endif /* NO_AES_MUTEX */
2995
2996
#ifndef NO_HASH_MUTEX
2997
int wolfSSL_HwHashMutexInit(void)
2998
{
2999
    return hwAlgoMutexInit(hash_mutex);
3000
}
3001
int wolfSSL_HwHashMutexLock(void)
3002
{
3003
    return hwAlgoMutexLock(hash_mutex);
3004
}
3005
int wolfSSL_HwHashMutexUnLock(void)
3006
{
3007
    return hwAlgoMutexUnLock(hash_mutex);
3008
}
3009
#endif /* NO_HASH_MUTEX */
3010
3011
#ifndef NO_PK_MUTEX
3012
int wolfSSL_HwPkMutexInit(void)
3013
{
3014
    return hwAlgoMutexInit(pk_mutex);
3015
}
3016
int wolfSSL_HwPkMutexLock(void)
3017
{
3018
    return hwAlgoMutexLock(pk_mutex);
3019
}
3020
int wolfSSL_HwPkMutexUnLock(void)
3021
{
3022
    return hwAlgoMutexUnLock(pk_mutex);
3023
}
3024
#endif /* NO_PK_MUTEX */
3025
3026
#endif /* WOLFSSL_CRYPT_HW_MUTEX && defined(WOLFSSL_ALGO_HW_MUTEX) */
3027
3028
/* ---------------------------------------------------------------------------*/
3029
/* Mutex Ports */
3030
/* ---------------------------------------------------------------------------*/
3031
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
3032
    static mutex_cb*     compat_mutex_cb = NULL;
3033
3034
    /* Function that locks or unlocks a mutex based on the flag passed in.
3035
     *
3036
     * flag lock or unlock i.e. CRYPTO_LOCK
3037
     * type the type of lock to unlock or lock
3038
     * file name of the file calling
3039
     * line the line number from file calling
3040
     */
3041
    int wc_LockMutex_ex(int flag, int type, const char* file, int line)
3042
    {
3043
        if (compat_mutex_cb != NULL) {
3044
            compat_mutex_cb(flag, type, file, line);
3045
            return 0;
3046
        }
3047
        else {
3048
            WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb");
3049
            return BAD_STATE_E;
3050
        }
3051
    }
3052
3053
3054
    /* Set the callback function to use for locking/unlocking mutex
3055
     *
3056
     * cb callback function to use
3057
     */
3058
    int wc_SetMutexCb(mutex_cb* cb)
3059
    {
3060
        compat_mutex_cb = cb;
3061
        return 0;
3062
    }
3063
3064
    /* Gets the current callback function in use for locking/unlocking mutex
3065
     *
3066
     */
3067
    mutex_cb* wc_GetMutexCb(void)
3068
    {
3069
        return compat_mutex_cb;
3070
    }
3071
#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */
3072
3073
#ifndef WOLFSSL_MUTEX_INITIALIZER
3074
/* Initialize a static mutex exactly once.
3075
 *
3076
 * Backstop for callers that reach a subsystem without wolfCrypt_Init(). One
3077
 * atomic with three states: 0 = uninitialized, 1 = in progress, 2 = ready.
3078
 * Losers of the race wait for the winner rather than failing, so callers do
3079
 * not need a retry path. Same pattern as the SP ECC cache locks.
3080
 *
3081
 * @param [in]      m     Mutex to initialize.
3082
 * @param [in, out] flag  Election state, statically zero initialized.
3083
 * @return  0 on success, or when the mutex is already initialized.
3084
 * @return  Error from wc_InitMutex() otherwise.
3085
 */
3086
int wc_local_InitMutexOnce(wolfSSL_Mutex* m, wc_MutexOnceFlag* flag)
3087
{
3088
    int ret = 0;
3089
#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED)
3090
    WC_ATOMIC_UINT_ARG expected;
3091
3092
    if (WOLFSSL_ATOMIC_LOAD(*flag) == 2) {
3093
        return 0;
3094
    }
3095
3096
    for (;;) {
3097
        expected = 0;
3098
        if (wolfSSL_Atomic_Uint_CompareExchange(flag, &expected, 1) == 1) {
3099
            /* Won the race. On failure reset to 0 so a later call retries. */
3100
            ret = wc_InitMutex(m);
3101
            WOLFSSL_ATOMIC_STORE(*flag, (ret == 0) ? 2U : 0U);
3102
            break;
3103
        }
3104
        if (expected == 2) {
3105
            /* Another thread completed the initialization. */
3106
            break;
3107
        }
3108
        /* Initialization in progress in another thread. */
3109
        WC_RELAX_LONG_LOOP();
3110
    }
3111
#else
3112
    /* No atomics to elect with: single-threaded cannot race, and opt-out
3113
     * builds keep their existing behavior. */
3114
    if (*flag != 2) {
3115
        ret = wc_InitMutex(m);
3116
        if (ret == 0) {
3117
            *flag = 2;
3118
        }
3119
    }
3120
#endif
3121
    return ret;
3122
}
3123
#endif /* !WOLFSSL_MUTEX_INITIALIZER */
3124
3125
#if defined(WC_MUTEX_OPS_INLINE)
3126
3127
    /* defined in headers */
3128
3129
#elif defined(SINGLE_THREADED)
3130
3131
    int wc_InitMutex(wolfSSL_Mutex* m)
3132
    {
3133
        (void)m;
3134
        return 0;
3135
    }
3136
3137
    int wc_FreeMutex(wolfSSL_Mutex *m)
3138
    {
3139
        (void)m;
3140
        return 0;
3141
    }
3142
3143
3144
    int wc_LockMutex(wolfSSL_Mutex *m)
3145
    {
3146
        (void)m;
3147
        return 0;
3148
    }
3149
3150
3151
    int wc_UnLockMutex(wolfSSL_Mutex *m)
3152
    {
3153
        (void)m;
3154
        return 0;
3155
    }
3156
3157
#elif defined(__WATCOMC__)
3158
3159
    int wc_InitMutex(wolfSSL_Mutex* m)
3160
    {
3161
    #ifdef __OS2__
3162
        DosCreateMutexSem( NULL, m, 0, FALSE );
3163
    #elif defined(__NT__)
3164
        InitializeCriticalSection(m);
3165
    #elif defined(__LINUX__)
3166
        if (pthread_mutex_init(m, NULL) )
3167
            return BAD_MUTEX_E;
3168
    #endif
3169
        return 0;
3170
    }
3171
3172
    int wc_FreeMutex(wolfSSL_Mutex* m)
3173
    {
3174
    #ifdef __OS2__
3175
        DosCloseMutexSem(*m);
3176
    #elif defined(__NT__)
3177
        DeleteCriticalSection(m);
3178
    #elif defined(__LINUX__)
3179
        if (pthread_mutex_destroy(m) )
3180
            return BAD_MUTEX_E;
3181
    #endif
3182
        return 0;
3183
    }
3184
3185
    int wc_LockMutex(wolfSSL_Mutex* m)
3186
    {
3187
    #ifdef __OS2__
3188
        DosRequestMutexSem(*m, SEM_INDEFINITE_WAIT);
3189
    #elif defined(__NT__)
3190
        EnterCriticalSection(m);
3191
    #elif defined(__LINUX__)
3192
        if (pthread_mutex_lock(m) )
3193
            return BAD_MUTEX_E;
3194
    #endif
3195
        return 0;
3196
    }
3197
3198
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3199
    {
3200
    #ifdef __OS2__
3201
        DosReleaseMutexSem(*m);
3202
    #elif defined(__NT__)
3203
        LeaveCriticalSection(m);
3204
    #elif defined(__LINUX__)
3205
        if (pthread_mutex_unlock(m) )
3206
            return BAD_MUTEX_E;
3207
    #endif
3208
        return 0;
3209
    }
3210
3211
    #if defined(WOLFSSL_USE_RWLOCK) && defined(__LINUX__)
3212
3213
    int wc_InitRwLock(wolfSSL_RwLock* m)
3214
    {
3215
        if (pthread_rwlock_init(m, NULL) )
3216
             return BAD_MUTEX_E;
3217
        return 0;
3218
    }
3219
3220
    int wc_FreeRwLock(wolfSSL_RwLock* m)
3221
    {
3222
        if (pthread_rwlock_destroy(m) )
3223
            return BAD_MUTEX_E;
3224
        return 0;
3225
    }
3226
3227
    int wc_LockRwLock_Wr(wolfSSL_RwLock* m)
3228
    {
3229
        if (pthread_rwlock_wrlock(m) )
3230
            return BAD_MUTEX_E;
3231
        return 0;
3232
    }
3233
3234
    int wc_LockRwLock_Rd(wolfSSL_RwLock* m)
3235
    {
3236
        if (pthread_rwlock_rdlock(m) )
3237
            return BAD_MUTEX_E;
3238
        return 0;
3239
    }
3240
3241
    int wc_UnLockRwLock(wolfSSL_RwLock* m)
3242
    {
3243
        if (pthread_rwlock_unlock(m) == 0)
3244
            return BAD_MUTEX_E;
3245
        return 0;
3246
    }
3247
3248
    #endif
3249
3250
#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \
3251
  defined(FREESCALE_FREE_RTOS)
3252
3253
    int wc_InitMutex(wolfSSL_Mutex* m)
3254
    {
3255
        int iReturn;
3256
3257
        *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex();
3258
        if( *m != NULL )
3259
            iReturn = 0;
3260
        else
3261
            iReturn = BAD_MUTEX_E;
3262
3263
        return iReturn;
3264
    }
3265
3266
    int wc_FreeMutex(wolfSSL_Mutex* m)
3267
    {
3268
        vSemaphoreDelete( *m );
3269
        return 0;
3270
    }
3271
3272
    int wc_LockMutex(wolfSSL_Mutex* m)
3273
    {
3274
        /* Assume an infinite block, or should there be zero block? */
3275
        xSemaphoreTake( *m, portMAX_DELAY );
3276
        return 0;
3277
    }
3278
3279
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3280
    {
3281
        xSemaphoreGive( *m );
3282
        return 0;
3283
    }
3284
3285
#elif defined(RTTHREAD)
3286
3287
    int wc_InitMutex(wolfSSL_Mutex* m)
3288
    {
3289
        int iReturn;
3290
3291
        *m = ( wolfSSL_Mutex ) rt_mutex_create("mutex",RT_IPC_FLAG_FIFO);
3292
        if( *m != NULL )
3293
            iReturn = 0;
3294
        else
3295
            iReturn = BAD_MUTEX_E;
3296
3297
3298
        return iReturn;
3299
    }
3300
3301
    int wc_FreeMutex(wolfSSL_Mutex* m)
3302
    {
3303
        rt_mutex_delete( *m );
3304
        return 0;
3305
    }
3306
3307
3308
    int wc_LockMutex(wolfSSL_Mutex* m)
3309
    {
3310
        /* Assume an infinite block, or should there be zero block? */
3311
        return rt_mutex_take( *m, RT_WAITING_FOREVER );
3312
    }
3313
3314
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3315
    {
3316
        return rt_mutex_release( *m );
3317
    }
3318
3319
#elif defined(WOLFSSL_SAFERTOS)
3320
3321
    int wc_InitMutex(wolfSSL_Mutex* m)
3322
    {
3323
        vSemaphoreCreateBinary(m->mutexBuffer, m->mutex);
3324
        if (m->mutex == NULL)
3325
            return BAD_MUTEX_E;
3326
3327
        return 0;
3328
    }
3329
3330
    int wc_FreeMutex(wolfSSL_Mutex* m)
3331
    {
3332
        (void)m;
3333
        return 0;
3334
    }
3335
3336
    int wc_LockMutex(wolfSSL_Mutex* m)
3337
    {
3338
        /* Assume an infinite block */
3339
        xSemaphoreTake(m->mutex, portMAX_DELAY);
3340
        return 0;
3341
    }
3342
3343
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3344
    {
3345
        xSemaphoreGive(m->mutex);
3346
        return 0;
3347
    }
3348
3349
#elif defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS)
3350
3351
    int wc_InitMutex(wolfSSL_Mutex* m)
3352
    {
3353
        InitializeCriticalSection(m);
3354
        return 0;
3355
    }
3356
3357
3358
    int wc_FreeMutex(wolfSSL_Mutex* m)
3359
    {
3360
        DeleteCriticalSection(m);
3361
        return 0;
3362
    }
3363
3364
3365
    int wc_LockMutex(wolfSSL_Mutex* m)
3366
    {
3367
        EnterCriticalSection(m);
3368
        return 0;
3369
    }
3370
3371
3372
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3373
    {
3374
        LeaveCriticalSection(m);
3375
        return 0;
3376
    }
3377
3378
#elif defined(MAXQ10XX_MUTEX)
3379
    static pthread_mutex_t *wcCryptHwSharedMutexPtr;
3380
    static pthread_once_t key_once_own_hw_mutex = PTHREAD_ONCE_INIT;
3381
    static pthread_key_t key_own_hw_mutex;
3382
3383
    static void destruct_key(void *buf)
3384
    {
3385
        if (buf != NULL) {
3386
            XFREE(buf, NULL, DYNAMIC_TYPE_OS_BUF);
3387
        }
3388
    }
3389
3390
    static void make_key_own_hw_mutex(void)
3391
    {
3392
        (void)pthread_key_create(&key_own_hw_mutex, destruct_key);
3393
    }
3394
3395
    int wc_InitMutex(wolfSSL_Mutex* m)
3396
    {
3397
        int created = 0;
3398
        void *addr = NULL;
3399
3400
        if (m != &wcCryptHwMutex) {
3401
            if (pthread_mutex_init(m, 0) == 0) {
3402
                return 0;
3403
            }
3404
            return BAD_MUTEX_E;
3405
        }
3406
3407
        /* try to open mutex memory */
3408
        int shm_fd = shm_open("/maxq-mutex", O_RDWR, 0666);
3409
        if (shm_fd < 0) {
3410
            /* create mutex memory */
3411
            shm_fd = shm_open("/maxq-mutex", O_RDWR | O_CREAT | O_EXCL, 0666);
3412
            created = 1;
3413
        }
3414
3415
        if (shm_fd < 0) {
3416
            WOLFSSL_MSG("wc_InitMutex: shm_open() failed");
3417
            return BAD_MUTEX_E;
3418
        }
3419
3420
        if (ftruncate(shm_fd, sizeof(pthread_mutex_t))) {
3421
            WOLFSSL_MSG("wc_InitMutex: ftruncate() failed");
3422
            return BAD_MUTEX_E;
3423
        }
3424
3425
        addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE,
3426
                    MAP_SHARED, shm_fd, 0);
3427
3428
        if (addr == MAP_FAILED) {
3429
            WOLFSSL_MSG("wc_InitMutex: mmap() failed");
3430
            return BAD_MUTEX_E;
3431
        }
3432
3433
        wcCryptHwSharedMutexPtr = (pthread_mutex_t *)addr;
3434
3435
        if (close(shm_fd)) {
3436
            WOLFSSL_MSG("wc_InitMutex: close() failed");
3437
            return BAD_MUTEX_E;
3438
        }
3439
3440
        if (created) {
3441
            /* initialize mutex */
3442
            pthread_mutexattr_t attr;
3443
            if (pthread_mutexattr_init(&attr)) {
3444
                WOLFSSL_MSG("wc_InitMutex: pthread_mutexattr_init() failed");
3445
                return BAD_MUTEX_E;
3446
            }
3447
3448
            if (pthread_mutexattr_setpshared(&attr,
3449
                                             PTHREAD_PROCESS_SHARED)) {
3450
                WOLFSSL_MSG(
3451
                    "wc_InitMutex: pthread_mutexattr_setpshared() failed");
3452
                return BAD_MUTEX_E;
3453
            }
3454
3455
            if (pthread_mutex_init(wcCryptHwSharedMutexPtr, &attr)) {
3456
                WOLFSSL_MSG("wc_InitMutex: pthread_mutex_init() failed");
3457
                return BAD_MUTEX_E;
3458
            }
3459
        }
3460
3461
        if (pthread_once(&key_once_own_hw_mutex, make_key_own_hw_mutex)) {
3462
            WOLFSSL_MSG("wc_InitMutex: pthread_once() failed");
3463
            return BAD_MUTEX_E;
3464
        }
3465
3466
        return 0;
3467
    }
3468
3469
    int wc_FreeMutex(wolfSSL_Mutex* m)
3470
    {
3471
        void *key_ptr = NULL;
3472
        if (m != &wcCryptHwMutex) {
3473
            if (pthread_mutex_destroy(m) == 0) {
3474
                return 0;
3475
            }
3476
            return BAD_MUTEX_E;
3477
        }
3478
3479
        if (wcCryptHwSharedMutexPtr) {
3480
            if (munmap((void *)wcCryptHwSharedMutexPtr,
3481
                       sizeof(pthread_mutex_t))) {
3482
                WOLFSSL_MSG("wc_FreeMutex: munmap() failed");
3483
                return BAD_MUTEX_E;
3484
            }
3485
3486
            wcCryptHwSharedMutexPtr = NULL;
3487
        }
3488
3489
        key_ptr = pthread_getspecific(key_own_hw_mutex);
3490
        if (key_ptr) {
3491
            *((int *)key_ptr) = 0;
3492
        }
3493
3494
        return 0;
3495
    }
3496
3497
    static int maxq_LockMutex(wolfSSL_Mutex* m, int trylock)
3498
    {
3499
        void *key_ptr = NULL;
3500
        int ret = 0;
3501
3502
        if (m != &wcCryptHwMutex) {
3503
            if (pthread_mutex_lock(m) == 0) {
3504
                return 0;
3505
            }
3506
            return BAD_MUTEX_E;
3507
        }
3508
3509
        if (wcCryptHwSharedMutexPtr == NULL) {
3510
            return BAD_MUTEX_E;
3511
        }
3512
3513
        key_ptr = pthread_getspecific(key_own_hw_mutex);
3514
        if (key_ptr == NULL) {
3515
            key_ptr = XMALLOC(sizeof(int), NULL, DYNAMIC_TYPE_OS_BUF);
3516
            if (key_ptr == NULL) {
3517
                return MEMORY_E;
3518
            }
3519
3520
            memset(key_ptr, 0, sizeof(int));
3521
3522
            if (pthread_setspecific(key_own_hw_mutex, key_ptr)) {
3523
                return THREAD_STORE_SET_E;
3524
            }
3525
        }
3526
        else {
3527
            if ((trylock == 0) && (*((int *)key_ptr) > 0)) {
3528
                *((int *)key_ptr) = *((int *)key_ptr) + 1;
3529
                return 0;
3530
            }
3531
        }
3532
3533
        if (trylock) {
3534
            ret = pthread_mutex_trylock(wcCryptHwSharedMutexPtr);
3535
        }
3536
        else {
3537
            ret = pthread_mutex_lock(wcCryptHwSharedMutexPtr);
3538
        }
3539
3540
        if (ret != 0) {
3541
            return BAD_MUTEX_E;
3542
        }
3543
3544
        *((int *)key_ptr) = 1;
3545
        return 0;
3546
    }
3547
3548
    int wc_LockMutex(wolfSSL_Mutex* m)
3549
    {
3550
        return maxq_LockMutex(m, 0);
3551
    }
3552
3553
    int maxq_CryptHwMutexTryLock()
3554
    {
3555
        /* Make sure HW Mutex has been initialized */
3556
        int ret = wolfSSL_CryptHwMutexInit();
3557
        if (ret == 0) {
3558
            ret = maxq_LockMutex(&wcCryptHwMutex, 1);
3559
        }
3560
        return ret;
3561
    }
3562
3563
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3564
    {
3565
        void *key_ptr = NULL;
3566
3567
        if (m != &wcCryptHwMutex) {
3568
            if (pthread_mutex_unlock(m) == 0) {
3569
                return 0;
3570
            }
3571
            return BAD_MUTEX_E;
3572
        }
3573
3574
        if (wcCryptHwSharedMutexPtr == NULL) {
3575
            return BAD_MUTEX_E;
3576
        }
3577
3578
        key_ptr = pthread_getspecific(key_own_hw_mutex);
3579
        if (key_ptr) {
3580
            if (*((int *)key_ptr) > 0) {
3581
                *((int *)key_ptr) = *((int *)key_ptr) - 1;
3582
                if (*((int *)key_ptr) > 0) {
3583
                    return 0;
3584
                }
3585
            }
3586
        }
3587
3588
        if (pthread_mutex_unlock(wcCryptHwSharedMutexPtr) != 0) {
3589
            return BAD_MUTEX_E;
3590
        }
3591
        return 0;
3592
    }
3593
3594
#elif defined(WOLFSSL_PTHREADS)
3595
3596
    #ifdef WOLFSSL_USE_RWLOCK
3597
        int wc_InitRwLock(wolfSSL_RwLock* m)
3598
        {
3599
            if (pthread_rwlock_init(m, NULL) == 0)
3600
                return 0;
3601
            else
3602
                return BAD_MUTEX_E;
3603
        }
3604
3605
        int wc_FreeRwLock(wolfSSL_RwLock* m)
3606
        {
3607
            if (pthread_rwlock_destroy(m) == 0)
3608
                return 0;
3609
            else
3610
                return BAD_MUTEX_E;
3611
        }
3612
3613
        int wc_LockRwLock_Wr(wolfSSL_RwLock* m)
3614
        {
3615
            if (pthread_rwlock_wrlock(m) == 0)
3616
                return 0;
3617
            else
3618
                return BAD_MUTEX_E;
3619
        }
3620
3621
        int wc_LockRwLock_Rd(wolfSSL_RwLock* m)
3622
        {
3623
            if (pthread_rwlock_rdlock(m) == 0)
3624
                return 0;
3625
            else
3626
                return BAD_MUTEX_E;
3627
        }
3628
3629
        int wc_UnLockRwLock(wolfSSL_RwLock* m)
3630
        {
3631
            if (pthread_rwlock_unlock(m) == 0)
3632
                return 0;
3633
            else
3634
                return BAD_MUTEX_E;
3635
        }
3636
    #endif
3637
3638
    int wc_InitMutex(wolfSSL_Mutex* m)
3639
0
    {
3640
0
        if (pthread_mutex_init(m, NULL) == 0)
3641
0
            return 0;
3642
0
        else
3643
0
            return BAD_MUTEX_E;
3644
0
    }
3645
3646
3647
    int wc_FreeMutex(wolfSSL_Mutex* m)
3648
0
    {
3649
0
        if (pthread_mutex_destroy(m) == 0)
3650
0
            return 0;
3651
0
        else
3652
0
            return BAD_MUTEX_E;
3653
0
    }
3654
3655
3656
    int wc_LockMutex(wolfSSL_Mutex* m)
3657
0
    {
3658
0
        if (pthread_mutex_lock(m) == 0)
3659
0
            return 0;
3660
0
        else
3661
0
            return BAD_MUTEX_E;
3662
0
    }
3663
3664
3665
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3666
0
    {
3667
0
        if (pthread_mutex_unlock(m) == 0)
3668
0
            return 0;
3669
0
        else
3670
0
            return BAD_MUTEX_E;
3671
0
    }
3672
#elif defined(WOLFSSL_VXWORKS)
3673
3674
    int wc_InitMutex(wolfSSL_Mutex* m)
3675
    {
3676
        if (m) {
3677
            if ((*m = semMCreate(0)) != SEM_ID_NULL)
3678
                return 0;
3679
        }
3680
        return BAD_MUTEX_E;
3681
    }
3682
3683
3684
    int wc_FreeMutex(wolfSSL_Mutex* m)
3685
    {
3686
        if (m) {
3687
            if (semDelete(*m) == OK)
3688
                return 0;
3689
        }
3690
        return BAD_MUTEX_E;
3691
    }
3692
3693
3694
    int wc_LockMutex(wolfSSL_Mutex* m)
3695
    {
3696
        if (m) {
3697
            if (semTake(*m, WAIT_FOREVER) == OK)
3698
                return 0;
3699
        }
3700
        return BAD_MUTEX_E;
3701
    }
3702
3703
3704
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3705
    {
3706
        if (m) {
3707
            if (semGive(*m) == OK)
3708
                return 0;
3709
        }
3710
        return BAD_MUTEX_E;
3711
    }
3712
3713
#elif defined(THREADX)
3714
3715
    int wc_InitMutex(wolfSSL_Mutex* m)
3716
    {
3717
        if (tx_mutex_create(m, (CHAR*)"wolfSSL Mutex", TX_NO_INHERIT) == 0)
3718
            return 0;
3719
        else
3720
            return BAD_MUTEX_E;
3721
    }
3722
3723
3724
    int wc_FreeMutex(wolfSSL_Mutex* m)
3725
    {
3726
        if (tx_mutex_delete(m) == 0)
3727
            return 0;
3728
        else
3729
            return BAD_MUTEX_E;
3730
    }
3731
3732
3733
    int wc_LockMutex(wolfSSL_Mutex* m)
3734
    {
3735
        if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
3736
            return 0;
3737
        else
3738
            return BAD_MUTEX_E;
3739
    }
3740
3741
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3742
    {
3743
        if (tx_mutex_put(m) == 0)
3744
            return 0;
3745
        else
3746
            return BAD_MUTEX_E;
3747
    }
3748
3749
#elif defined(WOLFSSL_DEOS)
3750
3751
    int wc_InitMutex(wolfSSL_Mutex* m)
3752
    {
3753
        mutexStatus mutStat;
3754
        /*
3755
        The empty string "" denotes an anonymous mutex, so objects do not cause name collisions.
3756
        `protectWolfSSLTemp` in an XML configuration element template describing a mutex.
3757
        */
3758
        if (m) {
3759
            mutStat = createMutex("", "protectWolfSSLTemp", m);
3760
            if (mutStat == mutexSuccess)
3761
                return 0;
3762
            else{
3763
                WOLFSSL_MSG("wc_InitMutex failed");
3764
                return mutStat;
3765
            }
3766
        }
3767
        return BAD_MUTEX_E;
3768
    }
3769
3770
    int wc_FreeMutex(wolfSSL_Mutex* m)
3771
    {
3772
        mutexStatus mutStat;
3773
        if (m) {
3774
            mutStat = deleteMutex(*m);
3775
            if (mutStat == mutexSuccess)
3776
                return 0;
3777
            else{
3778
                WOLFSSL_MSG("wc_FreeMutex failed");
3779
                return mutStat;
3780
            }
3781
        }
3782
        return BAD_MUTEX_E;
3783
    }
3784
3785
    int wc_LockMutex(wolfSSL_Mutex* m)
3786
    {
3787
        mutexStatus mutStat;
3788
        if (m) {
3789
            mutStat = lockMutex(*m);
3790
            if (mutStat == mutexSuccess)
3791
                return 0;
3792
            else{
3793
                WOLFSSL_MSG("wc_LockMutex failed");
3794
                return mutStat;
3795
            }
3796
        }
3797
        return BAD_MUTEX_E;
3798
    }
3799
3800
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3801
    {
3802
        mutexStatus mutStat;
3803
        if (m) {
3804
            mutStat = unlockMutex(*m);
3805
            if (mutStat== mutexSuccess)
3806
                return 0;
3807
            else{
3808
                WOLFSSL_MSG("wc_UnLockMutex failed");
3809
                return mutStat;
3810
            }
3811
        }
3812
        return BAD_MUTEX_E;
3813
    }
3814
3815
#elif defined(MICRIUM)
3816
    #if (OS_VERSION < 50000)
3817
        #define MICRIUM_ERR_TYPE OS_ERR
3818
        #define MICRIUM_ERR_NONE OS_ERR_NONE
3819
        #define MICRIUM_ERR_CODE(err) err
3820
    #else
3821
        #define MICRIUM_ERR_TYPE RTOS_ERR
3822
        #define MICRIUM_ERR_NONE RTOS_ERR_NONE
3823
        #define MICRIUM_ERR_CODE(err)    RTOS_ERR_CODE_GET(err)
3824
    #endif
3825
3826
    int wc_InitMutex(wolfSSL_Mutex* m)
3827
    {
3828
        MICRIUM_ERR_TYPE err;
3829
3830
        OSMutexCreate(m, "wolfSSL Mutex", &err);
3831
3832
        if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE)
3833
            return 0;
3834
        else
3835
            return BAD_MUTEX_E;
3836
    }
3837
3838
    int wc_FreeMutex(wolfSSL_Mutex* m)
3839
    {
3840
        #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED)
3841
            MICRIUM_ERR_TYPE err;
3842
3843
            OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err);
3844
3845
            if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE)
3846
                return 0;
3847
            else
3848
                return BAD_MUTEX_E;
3849
        #else
3850
            (void)m;
3851
            return 0;
3852
        #endif
3853
    }
3854
3855
    int wc_LockMutex(wolfSSL_Mutex* m)
3856
    {
3857
        MICRIUM_ERR_TYPE err;
3858
3859
        OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
3860
3861
        if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE)
3862
            return 0;
3863
        else
3864
            return BAD_MUTEX_E;
3865
    }
3866
3867
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3868
    {
3869
        MICRIUM_ERR_TYPE err;
3870
3871
        OSMutexPost(m, OS_OPT_POST_NONE, &err);
3872
3873
        if (MICRIUM_ERR_CODE(err) == MICRIUM_ERR_NONE)
3874
            return 0;
3875
        else
3876
            return BAD_MUTEX_E;
3877
    }
3878
3879
#elif defined(EBSNET)
3880
    #if (defined(RTPLATFORM) && (RTPLATFORM != 0))
3881
    int wc_InitMutex(wolfSSL_Mutex* m)
3882
    {
3883
        if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1)
3884
            return BAD_MUTEX_E;
3885
        else
3886
            return 0;
3887
    }
3888
3889
    int wc_FreeMutex(wolfSSL_Mutex* m)
3890
    {
3891
        rtp_sig_mutex_free(*m);
3892
        return 0;
3893
    }
3894
3895
    int wc_LockMutex(wolfSSL_Mutex* m)
3896
    {
3897
        if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0)
3898
            return 0;
3899
        else
3900
            return BAD_MUTEX_E;
3901
    }
3902
3903
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3904
    {
3905
        rtp_sig_mutex_release(*m);
3906
        return 0;
3907
    }
3908
3909
    int ebsnet_fseek(int a, long b, int c)
3910
    {
3911
        int retval;
3912
3913
        retval = vf_lseek(a, b, c);
3914
        if (retval > 0)
3915
            retval = 0;
3916
        else
3917
            retval =  -1;
3918
3919
        return(retval);
3920
    }
3921
    #else
3922
    static int rtip_semaphore_build(wolfSSL_Mutex *m)
3923
    {
3924
        KS_SEMAPHORE_BUILD(m)
3925
        return(RTP_TRUE);
3926
    }
3927
3928
    int wc_InitMutex(wolfSSL_Mutex* m)
3929
    {
3930
        if (rtip_semaphore_build(m) == RTP_FALSE)
3931
            return BAD_MUTEX_E;
3932
        else
3933
            return 0;
3934
    }
3935
3936
    int wc_FreeMutex(wolfSSL_Mutex* m)
3937
    {
3938
        KS_SEMAPHORE_FREE(*m);
3939
        return 0;
3940
    }
3941
3942
    int wc_LockMutex(wolfSSL_Mutex* m)
3943
    {
3944
        if (KS_SEMAPHORE_GET(*m))
3945
            return 0;
3946
        else
3947
            return BAD_MUTEX_E;
3948
    }
3949
3950
    int wc_UnLockMutex(wolfSSL_Mutex* m)
3951
    {
3952
        KS_SEMAPHORE_GIVE(*m);
3953
        return 0;
3954
    }
3955
    #endif
3956
    int ebsnet_fseek(int a, long b, int c)
3957
    {
3958
        int retval;
3959
3960
        retval = (int)vf_lseek(a, b, c);
3961
        if (retval > 0)
3962
            retval = 0;
3963
        else
3964
            retval =  -1;
3965
3966
        return(retval);
3967
    }
3968
3969
    int strcasecmp(const char *s1, const char *s2)
3970
    {
3971
        while (rtp_tolower(*s1) == rtp_tolower(*s2)) {
3972
            if (*s1 == '\0' || *s2 == '\0')
3973
                break;
3974
            s1++;
3975
            s2++;
3976
        }
3977
3978
        return rtp_tolower(*(unsigned char *) s1) -
3979
               rtp_tolower(*(unsigned char *) s2);
3980
    }
3981
3982
#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
3983
3984
    int wc_InitMutex(wolfSSL_Mutex* m)
3985
    {
3986
    #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2))
3987
        if (wolfCrypt_GetMode_fips() == FIPS_MODE_INIT)
3988
            return 0;
3989
    #endif
3990
        if (_mutex_init(m, NULL) == MQX_EOK)
3991
            return 0;
3992
        else
3993
            return BAD_MUTEX_E;
3994
    }
3995
3996
    int wc_FreeMutex(wolfSSL_Mutex* m)
3997
    {
3998
        if (_mutex_destroy(m) == MQX_EOK)
3999
            return 0;
4000
        else
4001
            return BAD_MUTEX_E;
4002
    }
4003
4004
    int wc_LockMutex(wolfSSL_Mutex* m)
4005
    {
4006
    #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2))
4007
        if (m->VALID != MUTEX_VALID) {
4008
            if (_mutex_init(m, NULL) != MQX_EOK)
4009
                return BAD_MUTEX_E;
4010
        }
4011
    #endif
4012
4013
        if (_mutex_lock(m) == MQX_EOK)
4014
            return 0;
4015
        else
4016
            return BAD_MUTEX_E;
4017
    }
4018
4019
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4020
    {
4021
    #if (defined(HAVE_FIPS) && FIPS_VERSION_EQ(5,2))
4022
        if (m->VALID != MUTEX_VALID) {
4023
            if (_mutex_init(m, NULL) != MQX_EOK)
4024
                return BAD_MUTEX_E;
4025
        }
4026
    #endif
4027
4028
        if (_mutex_unlock(m) == MQX_EOK)
4029
            return 0;
4030
        else
4031
            return BAD_MUTEX_E;
4032
    }
4033
4034
#elif defined(WOLFSSL_TIRTOS)
4035
    #include <xdc/runtime/Error.h>
4036
4037
    int wc_InitMutex(wolfSSL_Mutex* m)
4038
    {
4039
        Semaphore_Params params;
4040
        Error_Block eb;
4041
4042
        Error_init(&eb);
4043
        Semaphore_Params_init(&params);
4044
        params.mode = Semaphore_Mode_BINARY;
4045
4046
        *m = Semaphore_create(1, &params, &eb);
4047
        if (Error_check(&eb)) {
4048
            Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.",
4049
                NULL);
4050
            return BAD_MUTEX_E;
4051
        }
4052
        else
4053
            return 0;
4054
    }
4055
4056
    int wc_FreeMutex(wolfSSL_Mutex* m)
4057
    {
4058
        Semaphore_delete(m);
4059
4060
        return 0;
4061
    }
4062
4063
    int wc_LockMutex(wolfSSL_Mutex* m)
4064
    {
4065
        Semaphore_pend(*m, BIOS_WAIT_FOREVER);
4066
4067
        return 0;
4068
    }
4069
4070
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4071
    {
4072
        Semaphore_post(*m);
4073
4074
        return 0;
4075
    }
4076
4077
#elif defined(WOLFSSL_uITRON4)
4078
4079
    int wc_InitMutex(wolfSSL_Mutex* m)
4080
    {
4081
        int iReturn;
4082
        m->sem.sematr  = TA_TFIFO;
4083
        m->sem.isemcnt = 1;
4084
        m->sem.maxsem  = 1;
4085
        m->sem.name    = NULL;
4086
4087
        m->id = acre_sem(&m->sem);
4088
        if( m->id != E_OK )
4089
            iReturn = 0;
4090
        else
4091
            iReturn = BAD_MUTEX_E;
4092
4093
        return iReturn;
4094
    }
4095
4096
    int wc_FreeMutex(wolfSSL_Mutex* m)
4097
    {
4098
        del_sem( m->id );
4099
        return 0;
4100
    }
4101
4102
    int wc_LockMutex(wolfSSL_Mutex* m)
4103
    {
4104
        wai_sem(m->id);
4105
        return 0;
4106
    }
4107
4108
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4109
    {
4110
        sig_sem(m->id);
4111
        return 0;
4112
    }
4113
4114
    /****  uITRON malloc/free ***/
4115
    static ID ID_wolfssl_MPOOL = 0;
4116
    static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"};
4117
4118
    int uITRON4_minit(size_t poolsz) {
4119
        ER ercd;
4120
        wolfssl_MPOOL.mplsz = poolsz;
4121
        ercd = acre_mpl(&wolfssl_MPOOL);
4122
        if (ercd > 0) {
4123
            ID_wolfssl_MPOOL = ercd;
4124
            return 0;
4125
        } else {
4126
            return -1;
4127
        }
4128
    }
4129
4130
    void *uITRON4_malloc(size_t sz) {
4131
        ER ercd;
4132
        void *p = NULL;
4133
        ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p);
4134
        if (ercd == E_OK) {
4135
            return p;
4136
        } else {
4137
            return 0;
4138
        }
4139
    }
4140
4141
    void *uITRON4_realloc(void *p, size_t sz) {
4142
      ER ercd;
4143
      void *newp = NULL;
4144
      if(p) {
4145
          ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp);
4146
          if ((ercd == E_OK) && (newp != NULL)) {
4147
              XMEMCPY(newp, p, sz);
4148
              ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
4149
              if (ercd == E_OK) {
4150
                  return newp;
4151
              }
4152
          }
4153
      }
4154
      return 0;
4155
    }
4156
4157
    void uITRON4_free(void *p) {
4158
        ER ercd;
4159
        ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
4160
        if (ercd == E_OK) {
4161
            return;
4162
        } else {
4163
            return;
4164
        }
4165
    }
4166
4167
#elif defined(WOLFSSL_uTKERNEL2)
4168
4169
    int wc_InitMutex(wolfSSL_Mutex* m)
4170
    {
4171
        int iReturn;
4172
        m->sem.sematr  = TA_TFIFO;
4173
        m->sem.isemcnt = 1;
4174
        m->sem.maxsem  = 1;
4175
4176
        m->id = tk_cre_sem(&m->sem);
4177
        if( m->id != NULL )
4178
            iReturn = 0;
4179
        else
4180
            iReturn = BAD_MUTEX_E;
4181
4182
        return iReturn;
4183
    }
4184
4185
    int wc_FreeMutex(wolfSSL_Mutex* m)
4186
    {
4187
        tk_del_sem(m->id);
4188
        return 0;
4189
    }
4190
4191
    int wc_LockMutex(wolfSSL_Mutex* m)
4192
    {
4193
        tk_wai_sem(m->id, 1, TMO_FEVR);
4194
        return 0;
4195
    }
4196
4197
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4198
    {
4199
        tk_sig_sem(m->id, 1);
4200
        return 0;
4201
    }
4202
4203
    /****  uT-Kernel malloc/free ***/
4204
    static ID ID_wolfssl_MPOOL = 0;
4205
    static T_CMPL wolfssl_MPOOL = {
4206
        NULL,       /* Extended information */
4207
        TA_TFIFO,   /* Memory pool attribute */
4208
        0,          /* Size of whole memory pool (byte) */
4209
        "wolfSSL"   /* Object name (max 8-char) */
4210
    };
4211
4212
    int uTKernel_init_mpool(unsigned int sz) {
4213
        ER ercd;
4214
        wolfssl_MPOOL.mplsz = sz;
4215
        ercd = tk_cre_mpl(&wolfssl_MPOOL);
4216
        if (ercd > 0) {
4217
            ID_wolfssl_MPOOL = ercd;
4218
            return 0;
4219
        } else {
4220
            return (int)ercd;
4221
        }
4222
    }
4223
4224
    void *uTKernel_malloc(unsigned int sz) {
4225
        ER ercd;
4226
        void *p = NULL;
4227
        ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR);
4228
        if (ercd == E_OK) {
4229
            return p;
4230
        } else {
4231
            return 0;
4232
        }
4233
    }
4234
4235
    void *uTKernel_realloc(void *p, unsigned int sz) {
4236
      ER ercd;
4237
      void *newp = NULL;
4238
      if (p) {
4239
          ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR);
4240
          if ((ercd == E_OK) && (newp != NULL)) {
4241
              XMEMCPY(newp, p, sz);
4242
              ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
4243
              if (ercd == E_OK) {
4244
                  return newp;
4245
              }
4246
          }
4247
      }
4248
      return 0;
4249
    }
4250
4251
    void uTKernel_free(void *p) {
4252
        ER ercd;
4253
        ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
4254
        if (ercd == E_OK) {
4255
            return;
4256
        } else {
4257
            return;
4258
        }
4259
    }
4260
4261
#elif defined (WOLFSSL_FROSTED)
4262
4263
    int wc_InitMutex(wolfSSL_Mutex* m)
4264
    {
4265
        *m = mutex_init();
4266
        if (*m)
4267
            return 0;
4268
        else
4269
            return -1;
4270
    }
4271
4272
    int wc_FreeMutex(wolfSSL_Mutex* m)
4273
    {
4274
        mutex_destroy(*m);
4275
        return(0);
4276
    }
4277
4278
    int wc_LockMutex(wolfSSL_Mutex* m)
4279
    {
4280
        mutex_lock(*m);
4281
        return 0;
4282
    }
4283
4284
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4285
    {
4286
        mutex_unlock(*m);
4287
        return 0;
4288
    }
4289
4290
#elif defined(WOLFSSL_CMSIS_RTOS)
4291
4292
    #ifndef CMSIS_NMUTEX
4293
        #define CMSIS_NMUTEX 10
4294
    #endif
4295
    osMutexDef(wolfSSL_mt0);  osMutexDef(wolfSSL_mt1);  osMutexDef(wolfSSL_mt2);
4296
    osMutexDef(wolfSSL_mt3);  osMutexDef(wolfSSL_mt4);  osMutexDef(wolfSSL_mt5);
4297
    osMutexDef(wolfSSL_mt6);  osMutexDef(wolfSSL_mt7);  osMutexDef(wolfSSL_mt8);
4298
    osMutexDef(wolfSSL_mt9);
4299
4300
    static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0),
4301
        osMutex(wolfSSL_mt1),    osMutex(wolfSSL_mt2),   osMutex(wolfSSL_mt3),
4302
        osMutex(wolfSSL_mt4),    osMutex(wolfSSL_mt5),   osMutex(wolfSSL_mt6),
4303
        osMutex(wolfSSL_mt7),    osMutex(wolfSSL_mt8),   osMutex(wolfSSL_mt9) };
4304
4305
    static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0};
4306
4307
    int wc_InitMutex(wolfSSL_Mutex* m)
4308
    {
4309
        int i;
4310
4311
        if(!osKernelRunning()) {
4312
            return 0;
4313
        }
4314
4315
        for (i=0; i<CMSIS_NMUTEX; i++) {
4316
            if(CMSIS_mutexID[i] == 0) {
4317
                CMSIS_mutexID[i] = osMutexCreate(CMSIS_mutex[i]);
4318
                (*m) = CMSIS_mutexID[i];
4319
            return 0;
4320
            }
4321
        }
4322
        return -1;
4323
    }
4324
4325
    int wc_FreeMutex(wolfSSL_Mutex* m)
4326
    {
4327
        int i;
4328
4329
        if(!osKernelRunning()) {
4330
            return 0;
4331
        }
4332
4333
        osMutexDelete   (*m);
4334
        for (i=0; i<CMSIS_NMUTEX; i++) {
4335
            if(CMSIS_mutexID[i] == (*m)) {
4336
                CMSIS_mutexID[i] = 0;
4337
                return(0);
4338
            }
4339
        }
4340
        return(-1);
4341
    }
4342
4343
    int wc_LockMutex(wolfSSL_Mutex* m)
4344
    {
4345
        if(osKernelRunning()) {
4346
            osMutexWait(*m, osWaitForever);
4347
        }
4348
        return(0);
4349
    }
4350
4351
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4352
    {
4353
        if(osKernelRunning()) {
4354
            osMutexRelease (*m);
4355
        }
4356
        return 0;
4357
    }
4358
4359
#elif defined(WOLFSSL_CMSIS_RTOSv2)
4360
    int wc_InitMutex(wolfSSL_Mutex *m)
4361
    {
4362
        static const osMutexAttr_t attr = {
4363
            "wolfSSL_mutex", osMutexRecursive, NULL, 0};
4364
4365
        if ((*m = osMutexNew(&attr)) != NULL)
4366
            return 0;
4367
        else
4368
            return BAD_MUTEX_E;
4369
    }
4370
4371
    int wc_FreeMutex(wolfSSL_Mutex *m)
4372
    {
4373
        if (osMutexDelete(*m) == osOK)
4374
            return 0;
4375
        else
4376
            return BAD_MUTEX_E;
4377
    }
4378
4379
4380
    int wc_LockMutex(wolfSSL_Mutex *m)
4381
    {
4382
        if (osMutexAcquire(*m, osWaitForever) == osOK)
4383
            return 0;
4384
        else
4385
            return BAD_MUTEX_E;
4386
    }
4387
4388
    int wc_UnLockMutex(wolfSSL_Mutex *m)
4389
    {
4390
        if (osMutexRelease(*m) == osOK)
4391
            return 0;
4392
        else
4393
            return BAD_MUTEX_E;
4394
    }
4395
4396
#elif defined(WOLFSSL_MDK_ARM)
4397
4398
    int wc_InitMutex(wolfSSL_Mutex* m)
4399
    {
4400
        os_mut_init (m);
4401
        return 0;
4402
    }
4403
4404
    int wc_FreeMutex(wolfSSL_Mutex* m)
4405
    {
4406
        return(0);
4407
    }
4408
4409
    int wc_LockMutex(wolfSSL_Mutex* m)
4410
    {
4411
        os_mut_wait (m, 0xffff);
4412
        return(0);
4413
    }
4414
4415
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4416
    {
4417
        os_mut_release (m);
4418
        return 0;
4419
    }
4420
4421
#elif defined(INTIME_RTOS)
4422
4423
    int wc_InitMutex(wolfSSL_Mutex* m)
4424
    {
4425
        int ret = 0;
4426
4427
        if (m == NULL)
4428
            return BAD_FUNC_ARG;
4429
4430
        *m = CreateRtSemaphore(
4431
            1,                      /* initial unit count */
4432
            1,                      /* maximum unit count */
4433
            PRIORITY_QUEUING        /* creation flags: FIFO_QUEUING or PRIORITY_QUEUING */
4434
        );
4435
        if (*m == BAD_RTHANDLE) {
4436
            ret = GetLastRtError();
4437
            if (ret != E_OK)
4438
                ret = BAD_MUTEX_E;
4439
        }
4440
        return ret;
4441
    }
4442
4443
    int wc_FreeMutex(wolfSSL_Mutex* m)
4444
    {
4445
        int ret = 0;
4446
        BOOLEAN del;
4447
4448
        if (m == NULL)
4449
            return BAD_FUNC_ARG;
4450
4451
        del = DeleteRtSemaphore(
4452
            *m                      /* handle for RT semaphore */
4453
        );
4454
        if (del != TRUE)
4455
            ret = BAD_MUTEX_E;
4456
4457
        return ret;
4458
    }
4459
4460
    int wc_LockMutex(wolfSSL_Mutex* m)
4461
    {
4462
        int ret = 0;
4463
        DWORD lck;
4464
4465
        if (m == NULL)
4466
            return BAD_FUNC_ARG;
4467
4468
        lck = WaitForRtSemaphore(
4469
            *m,                     /* handle for RT semaphore */
4470
            1,                      /* number of units to wait for */
4471
            WAIT_FOREVER            /* number of milliseconds to wait for units */
4472
        );
4473
        if (lck == WAIT_FAILED) {
4474
            ret = GetLastRtError();
4475
            if (ret != E_OK)
4476
                ret = BAD_MUTEX_E;
4477
        }
4478
        return ret;
4479
    }
4480
4481
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4482
    {
4483
        int ret = 0;
4484
        BOOLEAN rel;
4485
4486
        if (m == NULL)
4487
            return BAD_FUNC_ARG;
4488
4489
        rel = ReleaseRtSemaphore(
4490
            *m,                     /* handle for RT semaphore */
4491
            1                       /* number of units to release to semaphore */
4492
        );
4493
        if (rel != TRUE)
4494
            ret = BAD_MUTEX_E;
4495
4496
        return ret;
4497
    }
4498
4499
#elif defined(WOLFSSL_NUCLEUS_1_2)
4500
4501
    int wc_InitMutex(wolfSSL_Mutex* m)
4502
    {
4503
        /* Call the Nucleus function to create the semaphore */
4504
        if (NU_Create_Semaphore(m, "WOLFSSL_MTX", 1,
4505
                                NU_PRIORITY) == NU_SUCCESS) {
4506
            return 0;
4507
        }
4508
4509
        return BAD_MUTEX_E;
4510
    }
4511
4512
    int wc_FreeMutex(wolfSSL_Mutex* m)
4513
    {
4514
        if (NU_Delete_Semaphore(m) == NU_SUCCESS)
4515
            return 0;
4516
4517
        return BAD_MUTEX_E;
4518
    }
4519
4520
    int wc_LockMutex(wolfSSL_Mutex* m)
4521
    {
4522
        /* passing suspend task option */
4523
        if (NU_Obtain_Semaphore(m, NU_SUSPEND) == NU_SUCCESS)
4524
            return 0;
4525
4526
        return BAD_MUTEX_E;
4527
    }
4528
4529
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4530
    {
4531
        if (NU_Release_Semaphore(m) == NU_SUCCESS)
4532
            return 0;
4533
4534
        return BAD_MUTEX_E;
4535
    }
4536
4537
#elif defined(WOLFSSL_ZEPHYR)
4538
4539
    int wc_InitMutex(wolfSSL_Mutex* m)
4540
    {
4541
        k_mutex_init(m);
4542
4543
        return 0;
4544
    }
4545
4546
    int wc_FreeMutex(wolfSSL_Mutex* m)
4547
    {
4548
        return 0;
4549
    }
4550
4551
    int wc_LockMutex(wolfSSL_Mutex* m)
4552
    {
4553
        int ret = 0;
4554
4555
        if (k_mutex_lock(m, K_FOREVER) != 0)
4556
            ret = BAD_MUTEX_E;
4557
4558
        return ret;
4559
    }
4560
4561
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4562
    {
4563
        k_mutex_unlock(m);
4564
4565
        return 0;
4566
    }
4567
4568
#elif defined(WOLFSSL_TELIT_M2MB)
4569
4570
    int wc_InitMutex(wolfSSL_Mutex* m)
4571
    {
4572
        M2MB_OS_RESULT_E        osRes;
4573
        M2MB_OS_MTX_ATTR_HANDLE mtxAttrHandle;
4574
        UINT32                  inheritVal = 1;
4575
4576
        osRes = m2mb_os_mtx_setAttrItem(&mtxAttrHandle,
4577
                                    CMDS_ARGS(
4578
                                      M2MB_OS_MTX_SEL_CMD_CREATE_ATTR, NULL,
4579
                                      M2MB_OS_MTX_SEL_CMD_NAME, "wolfMtx",
4580
                                      M2MB_OS_MTX_SEL_CMD_INHERIT, inheritVal
4581
                                    )
4582
                                );
4583
        if (osRes != M2MB_OS_SUCCESS) {
4584
            return BAD_MUTEX_E;
4585
        }
4586
4587
        osRes = m2mb_os_mtx_init(m, &mtxAttrHandle);
4588
        if (osRes != M2MB_OS_SUCCESS) {
4589
            return BAD_MUTEX_E;
4590
        }
4591
4592
        return 0;
4593
    }
4594
4595
    int wc_FreeMutex(wolfSSL_Mutex* m)
4596
    {
4597
        M2MB_OS_RESULT_E osRes;
4598
4599
        if (m == NULL)
4600
            return BAD_MUTEX_E;
4601
4602
        osRes = m2mb_os_mtx_deinit(*m);
4603
        if (osRes != M2MB_OS_SUCCESS) {
4604
            return BAD_MUTEX_E;
4605
        }
4606
4607
        return 0;
4608
    }
4609
4610
    int wc_LockMutex(wolfSSL_Mutex* m)
4611
    {
4612
        M2MB_OS_RESULT_E osRes;
4613
4614
        if (m == NULL)
4615
            return BAD_MUTEX_E;
4616
4617
        osRes = m2mb_os_mtx_get(*m, M2MB_OS_WAIT_FOREVER);
4618
        if (osRes != M2MB_OS_SUCCESS) {
4619
            return BAD_MUTEX_E;
4620
        }
4621
4622
        return 0;
4623
    }
4624
4625
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4626
    {
4627
        M2MB_OS_RESULT_E osRes;
4628
4629
        if (m == NULL)
4630
            return BAD_MUTEX_E;
4631
4632
        osRes = m2mb_os_mtx_put(*m);
4633
        if (osRes != M2MB_OS_SUCCESS) {
4634
            return BAD_MUTEX_E;
4635
        }
4636
4637
        return 0;
4638
    }
4639
4640
#elif defined(WOLFSSL_EMBOS)
4641
4642
    int wc_InitMutex(wolfSSL_Mutex* m)
4643
    {
4644
        int ret;
4645
4646
        OS_MUTEX_Create((OS_MUTEX*) m);
4647
        if (m != NULL)
4648
            ret = 0;
4649
        else
4650
            ret = BAD_MUTEX_E;
4651
4652
        return ret;
4653
    }
4654
4655
    int wc_FreeMutex(wolfSSL_Mutex* m)
4656
    {
4657
        OS_MUTEX_Delete((OS_MUTEX*) m);
4658
        return 0;
4659
    }
4660
4661
    int wc_LockMutex(wolfSSL_Mutex* m)
4662
    {
4663
        OS_MUTEX_LockBlocked((OS_MUTEX*) m);
4664
        return 0;
4665
    }
4666
4667
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4668
    {
4669
        OS_MUTEX_Unlock((OS_MUTEX*) m);
4670
        return 0;
4671
    }
4672
4673
#elif defined(NETOS)
4674
4675
    int wc_InitMutex(wolfSSL_Mutex* m)
4676
    {
4677
        if (tx_mutex_create(&ready->mutex, "wolfSSL Lock", TX_INHERIT)
4678
                == TX_SUCCESS)
4679
            return 0;
4680
        else
4681
            return BAD_MUTEX_E;
4682
    }
4683
4684
    int wc_FreeMutex(wolfSSL_Mutex* m)
4685
    {
4686
        if (tx_mutex_delete(&ready->mutex) == TX_SUCCESS)
4687
            return 0;
4688
        else
4689
            return BAD_MUTEX_E;
4690
    }
4691
4692
    int wc_LockMutex(wolfSSL_Mutex* m)
4693
    {
4694
4695
    }
4696
4697
    int wc_UnLockMutex(wolfSSL_Mutex* m)
4698
    {
4699
4700
    }
4701
4702
#elif defined(WOLFSSL_USER_MUTEX)
4703
4704
    /* Use user own mutex */
4705
4706
    /*
4707
    int wc_InitMutex(wolfSSL_Mutex* m) { ... }
4708
    int wc_FreeMutex(wolfSSL_Mutex *m) { ... }
4709
    int wc_LockMutex(wolfSSL_Mutex *m) { ... }
4710
    int wc_UnLockMutex(wolfSSL_Mutex *m) { ... }
4711
    */
4712
4713
#else
4714
    #warning No mutex handling defined
4715
4716
#endif
4717
#if !defined(WOLFSSL_USE_RWLOCK) || defined(SINGLE_THREADED) || \
4718
    (defined(WC_MUTEX_OPS_INLINE) && !defined(WC_RWLOCK_OPS_INLINE))
4719
    int wc_InitRwLock(wolfSSL_RwLock* m)
4720
0
    {
4721
0
        return wc_InitMutex(m);
4722
0
    }
4723
4724
    int wc_FreeRwLock(wolfSSL_RwLock* m)
4725
0
    {
4726
0
        return wc_FreeMutex(m);
4727
0
    }
4728
4729
    int wc_LockRwLock_Wr(wolfSSL_RwLock* m)
4730
0
    {
4731
0
        return wc_LockMutex(m);
4732
0
    }
4733
4734
    int wc_LockRwLock_Rd(wolfSSL_RwLock* m)
4735
0
    {
4736
0
        return wc_LockMutex(m);
4737
0
    }
4738
4739
    int wc_UnLockRwLock(wolfSSL_RwLock* m)
4740
0
    {
4741
0
        return wc_UnLockMutex(m);
4742
0
    }
4743
#endif
4744
4745
#ifndef NO_ASN_TIME
4746
#if defined(_WIN32_WCE)
4747
time_t windows_time(time_t* timer)
4748
{
4749
    SYSTEMTIME     sysTime;
4750
    FILETIME       fTime;
4751
    ULARGE_INTEGER intTime;
4752
4753
4754
    GetSystemTime(&sysTime);
4755
    SystemTimeToFileTime(&sysTime, &fTime);
4756
4757
    XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
4758
    /* subtract EPOCH */
4759
    intTime.QuadPart -= 0x19db1ded53e8000;
4760
    /* to secs */
4761
    intTime.QuadPart /= 10000000;
4762
4763
    if (timer != NULL)
4764
        *timer = (time_t)intTime.QuadPart;
4765
4766
    return (time_t)intTime.QuadPart;
4767
}
4768
#endif /*  _WIN32_WCE */
4769
4770
#if defined(WOLFSSL_GMTIME)
4771
struct tm* gmtime_r(const time_t* timer, struct tm *ret)
4772
{
4773
    #define YEAR0          1900
4774
    #define EPOCH_YEAR     1970
4775
    #define SECS_DAY       (24L * 60L * 60L)
4776
    #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
4777
    #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
4778
4779
    static const int _ytab[2][12] =
4780
    {
4781
        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
4782
        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
4783
    };
4784
4785
    time_t secs = *timer;
4786
    unsigned long dayclock, dayno;
4787
    int year = EPOCH_YEAR;
4788
4789
    dayclock = (unsigned long)secs % SECS_DAY;
4790
    dayno    = (unsigned long)secs / SECS_DAY;
4791
4792
    ret->tm_sec  = (int) dayclock % 60;
4793
    ret->tm_min  = (int)(dayclock % 3600) / 60;
4794
    ret->tm_hour = (int) dayclock / 3600;
4795
    ret->tm_wday = (int) (dayno + 4) % 7;        /* day 0 a Thursday */
4796
4797
    while(dayno >= (unsigned long)YEARSIZE(year)) {
4798
        dayno -= YEARSIZE(year);
4799
        year++;
4800
    }
4801
4802
    ret->tm_year = year - YEAR0;
4803
    ret->tm_yday = (int)dayno;
4804
    ret->tm_mon  = 0;
4805
4806
    while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
4807
        dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
4808
        ret->tm_mon++;
4809
    }
4810
4811
    ret->tm_mday  = (int)++dayno;
4812
#ifndef WOLFSSL_LINUXKM
4813
    ret->tm_isdst = 0;
4814
#endif
4815
4816
    return ret;
4817
}
4818
4819
struct tm* gmtime(const time_t* timer) {
4820
    static struct tm st_time;
4821
    return gmtime_r(timer, &st_time);
4822
}
4823
4824
#endif /* WOLFSSL_GMTIME */
4825
4826
4827
#if defined(HAVE_RTP_SYS)
4828
#define YEAR0          1900
4829
4830
struct tm* rtpsys_gmtime(const time_t* timer)       /* has a gmtime() but hangs */
4831
{
4832
    static struct tm st_time;
4833
    struct tm* ret = &st_time;
4834
4835
    DC_RTC_CALENDAR cal;
4836
    dc_rtc_time_get(&cal, TRUE);
4837
4838
    ret->tm_year  = cal.year - YEAR0;       /* gm starts at 1900 */
4839
    ret->tm_mon   = cal.month - 1;          /* gm starts at 0 */
4840
    ret->tm_mday  = cal.day;
4841
    ret->tm_hour  = cal.hour;
4842
    ret->tm_min   = cal.minute;
4843
    ret->tm_sec   = cal.second;
4844
4845
    return ret;
4846
}
4847
4848
#endif /* HAVE_RTP_SYS */
4849
4850
4851
#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
4852
4853
/*
4854
 * time() is just a stub in Microchip libraries. We need our own
4855
 * implementation. Use SNTP client to get seconds since epoch.
4856
 */
4857
time_t pic32_time(time_t* timer)
4858
{
4859
#ifdef MICROCHIP_TCPIP_V5
4860
    DWORD sec = 0;
4861
#else
4862
    word32 sec = 0;
4863
#endif
4864
4865
#ifdef MICROCHIP_MPLAB_HARMONY
4866
    sec = TCPIP_SNTP_UTCSecondsGet();
4867
#else
4868
    sec = SNTPGetUTCSeconds();
4869
#endif
4870
4871
    if (timer != NULL)
4872
        *timer = (time_t)sec;
4873
4874
    return (time_t)sec;
4875
}
4876
4877
#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */
4878
4879
#if defined(WOLFSSL_DEOS) || defined(WOLFSSL_DEOS_RTEMS)
4880
4881
time_t deos_time(time_t* timer)
4882
{
4883
    const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
4884
    const volatile word32 *systemTickPtr = systemTickPointer();
4885
4886
    if (timer != NULL)
4887
        *timer = *systemTickPtr/systemTickTimeInHz;
4888
4889
    #if defined(CURRENT_UNIX_TIMESTAMP)
4890
        /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */
4891
        return (time_t) (*systemTickPtr/systemTickTimeInHz) + CURRENT_UNIX_TIMESTAMP;
4892
    #else
4893
        return (time_t) *systemTickPtr/systemTickTimeInHz;
4894
    #endif
4895
}
4896
#endif /* WOLFSSL_DEOS || WOLFSSL_DEOS_RTEMS */
4897
4898
#if defined(FREESCALE_RTC)
4899
#include "fsl_rtc.h"
4900
time_t fsl_time(time_t* t)
4901
{
4902
    *t = RTC_GetSecondsTimerCount(RTC);
4903
    return *t;
4904
}
4905
#endif
4906
4907
#if defined(FREESCALE_SNVS_RTC)
4908
time_t fsl_time(time_t* t)
4909
{
4910
    struct tm tm_time;
4911
    time_t ret;
4912
4913
    snvs_hp_rtc_datetime_t rtcDate;
4914
    snvs_hp_rtc_config_t snvsRtcConfig;
4915
4916
    SNVS_HP_RTC_GetDefaultConfig(&snvsRtcConfig);
4917
    SNVS_HP_RTC_Init(SNVS, &snvsRtcConfig);
4918
4919
    SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);
4920
4921
    tm_time.tm_year  = rtcDate.year;
4922
    tm_time.tm_mon   = rtcDate.month;
4923
    tm_time.tm_mday  = rtcDate.day;
4924
    tm_time.tm_hour  = rtcDate.hour;
4925
    tm_time.tm_min   = rtcDate.minute;
4926
    tm_time.tm_sec   = rtcDate.second;
4927
4928
    ret = mktime(&tm_time);
4929
    if (t != NULL)
4930
        *t = ret;
4931
    return ret;
4932
}
4933
#endif
4934
4935
/* Matches the XTIME mapping's gate in wc_port.h, so this is not built when
4936
 * that mapping is excluded. */
4937
#if defined(WOLFSSL_OPTEE) && !defined(NO_ASN_TIME)
4938
4939
time_t optee_time(time_t* timer)
4940
{
4941
    TEE_Time reeTime;
4942
4943
    /* Normal-world clock, so not a trusted time source. See wc_port.h. */
4944
    TEE_GetREETime(&reeTime);
4945
4946
    if (timer != NULL)
4947
        *timer = (time_t)reeTime.seconds;
4948
4949
    return (time_t)reeTime.seconds;
4950
}
4951
4952
#endif /* WOLFSSL_OPTEE && !NO_ASN_TIME */
4953
4954
#if defined(MICRIUM)
4955
4956
time_t micrium_time(time_t* timer)
4957
{
4958
    CLK_TS_SEC sec;
4959
4960
    Clk_GetTS_Unix(&sec);
4961
4962
    if (timer != NULL)
4963
        *timer = sec;
4964
4965
    return (time_t) sec;
4966
}
4967
4968
#endif /* MICRIUM */
4969
4970
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
4971
4972
time_t mqx_time(time_t* timer)
4973
{
4974
    TIME_STRUCT time_s;
4975
4976
    _time_get(&time_s);
4977
4978
    if (timer != NULL)
4979
        *timer = (time_t)time_s.SECONDS;
4980
4981
    return (time_t)time_s.SECONDS;
4982
}
4983
4984
#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */
4985
4986
#if defined(MAX3266X_RTC)
4987
    #define XTIME wc_MXC_RTC_Time
4988
#endif
4989
4990
#if defined(WOLFSSL_TIRTOS) && defined(USER_TIME)
4991
4992
time_t XTIME(time_t * timer)
4993
{
4994
    time_t sec = 0;
4995
4996
    sec = (time_t) Seconds_get();
4997
4998
    if (timer != NULL)
4999
        *timer = sec;
5000
5001
    return sec;
5002
}
5003
5004
#endif /* WOLFSSL_TIRTOS */
5005
5006
#if defined(WOLFSSL_XILINX)
5007
#include "xrtcpsu.h"
5008
5009
time_t xilinx_time(time_t * timer)
5010
{
5011
    time_t sec = 0;
5012
    XRtcPsu_Config* con;
5013
    XRtcPsu         rtc;
5014
5015
    con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
5016
    if (con != NULL) {
5017
        if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) {
5018
            sec = (time_t)XRtcPsu_GetCurrentTime(&rtc);
5019
        }
5020
        else {
5021
            WOLFSSL_MSG("Unable to initialize RTC");
5022
        }
5023
    }
5024
5025
    if (timer != NULL)
5026
        *timer = sec;
5027
5028
    return sec;
5029
}
5030
5031
#endif /* WOLFSSL_XILINX */
5032
5033
#if defined(WOLFSSL_ZEPHYR)
5034
5035
time_t z_time(time_t * timer)
5036
{
5037
    #if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM)
5038
5039
    /* native_sim: read the simulator RTC for a real host wall-clock. The
5040
     * real-target RTC/libc gate below is compiled out under the host libc. */
5041
    uint32_t nsec = 0;
5042
    uint64_t sec = 0;
5043
5044
    native_rtc_gettime(RTC_CLOCK_PSEUDOHOSTREALTIME, &nsec, &sec);
5045
5046
    if (timer != NULL)
5047
        *timer = sec;
5048
5049
    return sec;
5050
5051
    #else
5052
5053
    struct timespec ts = { 0 };
5054
5055
    #if defined(CONFIG_RTC) && \
5056
        (defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC))
5057
5058
    /* Try to obtain the actual time from an RTC */
5059
    static const struct device *rtc = DEVICE_DT_GET(DT_NODELABEL(rtc));
5060
5061
    if (device_is_ready(rtc)) {
5062
        struct rtc_time rtc_time;
5063
        struct tm *tm_time = rtc_time_to_tm(&rtc_time);
5064
5065
        int ret = rtc_get_time(rtc, &rtc_time);
5066
5067
        if (ret == 0) {
5068
            time_t epochTime = mktime(tm_time);
5069
5070
            if (timer != NULL)
5071
                *timer = epochTime;
5072
5073
            return epochTime;
5074
        }
5075
    }
5076
    #endif /* CONFIG_RTC && (CONFIG_PICOLIBC || CONFIG_NEWLIB_LIBC) */
5077
5078
    /* Fallback to uptime since boot. This works for relative times, but
5079
     * not for ASN.1 date validation */
5080
    #ifdef SYS_CLOCK_REALTIME
5081
    if (sys_clock_gettime(SYS_CLOCK_REALTIME, &ts) == 0)
5082
    #else
5083
    if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
5084
    #endif
5085
        if (timer != NULL)
5086
            *timer = ts.tv_sec;
5087
5088
    return ts.tv_sec;
5089
5090
    #endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */
5091
}
5092
5093
#endif /* WOLFSSL_ZEPHYR */
5094
5095
5096
#if defined(WOLFSSL_WICED)
5097
    #ifndef WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME
5098
        #error Please define WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME at build time.
5099
    #endif /* WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME */
5100
5101
time_t wiced_pseudo_unix_epoch_time(time_t * timer)
5102
{
5103
    time_t epoch_time;
5104
    /* The time() function return uptime on WICED platform. */
5105
    epoch_time = time(NULL) + WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME;
5106
5107
    if (timer != NULL) {
5108
        *timer = epoch_time;
5109
    }
5110
    return epoch_time;
5111
}
5112
#endif /* WOLFSSL_WICED */
5113
5114
#ifdef WOLFSSL_TELIT_M2MB
5115
    time_t m2mb_xtime(time_t * timer)
5116
    {
5117
        time_t myTime = 0;
5118
        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
5119
        if (fd != -1) {
5120
            M2MB_RTC_TIMEVAL_T timeval;
5121
5122
            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
5123
5124
            myTime = timeval.sec;
5125
5126
            m2mb_rtc_close(fd);
5127
        }
5128
        return myTime;
5129
    }
5130
    #ifdef WOLFSSL_TLS13
5131
    time_t m2mb_xtime_ms(time_t * timer)
5132
    {
5133
        time_t myTime = 0;
5134
        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
5135
        if (fd != -1) {
5136
            M2MB_RTC_TIMEVAL_T timeval;
5137
5138
            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
5139
5140
            myTime = timeval.sec + timeval.msec;
5141
5142
            m2mb_rtc_close(fd);
5143
        }
5144
        return myTime;
5145
    }
5146
    #endif /* WOLFSSL_TLS13 */
5147
    #ifndef NO_CRYPT_BENCHMARK
5148
    double m2mb_xtime_bench(int reset)
5149
    {
5150
        double myTime = 0;
5151
        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
5152
        if (fd != -1) {
5153
            M2MB_RTC_TIMEVAL_T timeval;
5154
5155
            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
5156
5157
            myTime = (double)timeval.sec + ((double)timeval.msec / 1000);
5158
5159
            m2mb_rtc_close(fd);
5160
        }
5161
        return myTime;
5162
    }
5163
    #endif /* !NO_CRYPT_BENCHMARK */
5164
#endif /* WOLFSSL_TELIT_M2MB */
5165
5166
5167
#if defined(WOLFSSL_LINUXKM)
5168
/* linuxkm XTIME() implementation lives in linuxkm/module_hooks.c */
5169
#endif /* WOLFSSL_LINUXKM */
5170
5171
#ifdef HAL_RTC_MODULE_ENABLED
5172
extern RTC_HandleTypeDef hrtc;
5173
time_t stm32_hal_time(time_t *t1)
5174
{
5175
    struct tm tm_time;
5176
    time_t ret;
5177
    RTC_TimeTypeDef time;
5178
    RTC_DateTypeDef date;
5179
5180
    XMEMSET(&tm_time, 0, sizeof(struct tm));
5181
5182
    /* order of GetTime followed by GetDate required here due to STM32 HW
5183
     * requirement */
5184
    HAL_RTC_GetTime(&hrtc, &time, FORMAT_BIN);
5185
    HAL_RTC_GetDate(&hrtc, &date, FORMAT_BIN);
5186
5187
    /* RTC year is 0-99 and "struct tm" is 1900+, so assume after year 2000 */
5188
    tm_time.tm_year  = date.Year + 100;
5189
    /* RTC month is 1-12 and "struct tm" is 0-12, so subtract 1 */
5190
    tm_time.tm_mon   = date.Month - 1;
5191
    tm_time.tm_mday  = date.Date;
5192
    tm_time.tm_hour  = time.Hours;
5193
    tm_time.tm_min   = time.Minutes;
5194
    tm_time.tm_sec   = time.Seconds;
5195
5196
    ret = mktime(&tm_time);
5197
    if (t1 != NULL)
5198
        *t1 = ret;
5199
    return ret;
5200
}
5201
#endif /* HAL_RTC_MODULE_ENABLED */
5202
5203
#endif /* !NO_ASN_TIME */
5204
5205
#if (!defined(WOLFSSL_LEANPSK) && !defined(STRING_USER)) || \
5206
    defined(USE_WOLF_STRNSTR)
5207
char* wolfSSL_strnstr(const char* s1, const char* s2, size_t n)
5208
0
{
5209
0
    size_t s2_len = XSTRLEN(s2);
5210
5211
0
    if (s2_len == 0)
5212
0
        return (char *)(wc_ptr_t)s1;
5213
5214
0
    while (n >= s2_len && s1[0]) {
5215
0
        if (s1[0] == s2[0])
5216
0
            if (XMEMCMP(s1, s2, s2_len) == 0)
5217
0
                return (char *)(wc_ptr_t)s1;
5218
0
        s1++;
5219
0
        n--;
5220
0
    }
5221
5222
0
    return NULL;
5223
0
}
5224
#endif
5225
5226
5227
/* custom memory wrappers */
5228
#ifdef WOLFSSL_NUCLEUS_1_2
5229
5230
    /* system memory pool */
5231
    extern NU_MEMORY_POOL System_Memory;
5232
5233
    void* nucleus_malloc(unsigned long size, void* heap, int type)
5234
    {
5235
        STATUS status;
5236
        void*  stack_ptr;
5237
5238
        status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size,
5239
                                    NU_NO_SUSPEND);
5240
        if (status == NU_SUCCESS) {
5241
            return 0;
5242
        } else {
5243
            return stack_ptr;
5244
        }
5245
    }
5246
5247
    void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type)
5248
    {
5249
        DM_HEADER* old_header;
5250
        word32     old_size, copy_size;
5251
        void*      new_mem;
5252
5253
        /* if ptr is NULL, behave like malloc */
5254
        new_mem = nucleus_malloc(size, NULL, 0);
5255
        if (new_mem == 0 || ptr == 0) {
5256
            return new_mem;
5257
        }
5258
5259
        /* calculate old memory block size */
5260
        /* mem pointers stored in block headers (ref dm_defs.h) */
5261
        old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD);
5262
        old_size   = (byte*)old_header->dm_next_memory - (byte*)ptr;
5263
5264
        /* copy old to new */
5265
        if (old_size < size) {
5266
            copy_size = old_size;
5267
        } else {
5268
            copy_size = size;
5269
        }
5270
        XMEMCPY(new_mem, ptr, copy_size);
5271
5272
        /* free old */
5273
        nucleus_free(ptr, NULL, 0);
5274
5275
        return new_mem;
5276
    }
5277
5278
    void nucleus_free(void* ptr, void* heap, int type)
5279
    {
5280
        if (ptr != NULL)
5281
            NU_Deallocate_Memory(ptr);
5282
    }
5283
5284
#endif /* WOLFSSL_NUCLEUS_1_2 */
5285
5286
#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH)
5287
    #include <wolfcrypt/src/port/ti/ti-ccm.c>  /* initialize and Mutex for TI Crypt Engine */
5288
    #include <wolfcrypt/src/port/ti/ti-hash.c> /* md5, sha1, sha224, sha256 */
5289
#endif
5290
5291
#ifndef SINGLE_THREADED
5292
5293
/* Environment-specific multi-thread implementation check  */
5294
#if defined(__WATCOMC__)
5295
5296
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5297
        THREAD_CB cb, void* arg)
5298
    {
5299
        if (thread == NULL || cb == NULL)
5300
            return BAD_FUNC_ARG;
5301
    #if defined(__OS2__)
5302
        *thread = _beginthread(cb, NULL, 0, arg);
5303
        if (*thread == INVALID_THREAD_VAL) {
5304
            return MEMORY_E;
5305
        }
5306
    #elif defined(__NT__)
5307
        /* Use _beginthreadex instead of _beginthread because of:
5308
         *   _beginthreadex is safer to use than _beginthread. If the thread
5309
         *   that's generated by _beginthread exits quickly, the handle that's
5310
         *   returned to the caller of _beginthread might be invalid or point
5311
         *   to another thread. However, the handle that's returned by
5312
         *   _beginthreadex has to be closed by the caller of _beginthreadex,
5313
         *   so it's guaranteed to be a valid handle if _beginthreadex didn't
5314
         *   return an error.*/
5315
        *thread = _beginthreadex(NULL, 0, cb, arg, 0, NULL);
5316
        if (*thread == 0) {
5317
            *thread = INVALID_THREAD_VAL;
5318
            return MEMORY_E;
5319
        }
5320
    #elif defined(__LINUX__)
5321
        if (pthread_create(thread, NULL, cb, arg))
5322
            return MEMORY_E;
5323
    #endif
5324
        return 0;
5325
    }
5326
5327
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5328
    {
5329
        int ret = 0;
5330
5331
        if (thread == INVALID_THREAD_VAL)
5332
            return BAD_FUNC_ARG;
5333
    #if defined(__OS2__)
5334
        DosWaitThread(&thread, DCWW_WAIT);
5335
    #elif defined(__NT__)
5336
        /* We still want to attempt to close the thread handle even on error */
5337
        if (WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_FAILED)
5338
            ret = MEMORY_E;
5339
        if (CloseHandle((HANDLE)thread) == 0)
5340
            ret = MEMORY_E;
5341
    #elif defined(__LINUX__)
5342
        if (pthread_join(thread, NULL) != 0)
5343
            ret = MEMORY_E;
5344
    #endif
5345
        return ret;
5346
    }
5347
5348
    #if defined(WOLFSSL_THREAD_NO_JOIN)
5349
    int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg)
5350
    {
5351
        THREAD_TYPE thread;
5352
        int ret = 0;
5353
5354
        if (cb == NULL)
5355
            return BAD_FUNC_ARG;
5356
    #if defined(__OS2__)
5357
        thread = _beginthread(cb, NULL, 0, arg);
5358
        if (thread == INVALID_THREAD_VAL)
5359
            ret = MEMORY_E;
5360
    #elif defined(__NT__)
5361
        thread = _beginthread(cb, 0, arg);
5362
        if (thread == -1L)
5363
            ret = MEMORY_E;
5364
    #elif defined(__LINUX__)
5365
        XMEMSET(&thread, 0, sizeof(thread));
5366
        ret = wolfSSL_NewThread(&thread, cb, arg);
5367
        if (ret == 0)
5368
            ret = pthread_detach(thread);
5369
    #endif
5370
        return ret;
5371
    }
5372
    #endif
5373
5374
    #ifdef WOLFSSL_COND
5375
    int wolfSSL_CondInit(COND_TYPE* cond)
5376
    {
5377
        if (cond == NULL)
5378
            return BAD_FUNC_ARG;
5379
    #if defined(__MACH__)
5380
        cond->cond = dispatch_semaphore_create(0);
5381
        if (cond->cond == NULL)
5382
            return MEMORY_E;
5383
5384
        /* dispatch_release() fails hard, with Trace/BPT trap signal, if the
5385
         * sem's internal count is less than the value passed in with
5386
         * dispatch_semaphore_create().  work around this by initializing
5387
         * with 0, then incrementing it afterwards.
5388
         */
5389
        if (dispatch_semaphore_signal(s->sem) < 0) {
5390
            dispatch_release(s->sem);
5391
            return MEMORY_E;
5392
        }
5393
    #elif defined(__OS2__)
5394
        DosCreateMutexSem( NULL, &cond->mutex, 0, FALSE );
5395
        DosCreateEventSem( NULL, &cond->cond, DCE_POSTONE, FALSE );
5396
    #elif defined(__NT__)
5397
        cond->cond = CreateEventA(NULL, FALSE, FALSE, NULL);
5398
        if (cond->cond == NULL)
5399
            return MEMORY_E;
5400
5401
        if (wc_InitMutex(&cond->mutex) != 0) {
5402
            if (CloseHandle(cond->cond) == 0)
5403
                return MEMORY_E;
5404
            return MEMORY_E;
5405
        }
5406
    #elif defined(__LINUX__)
5407
        if (pthread_mutex_init(&cond->mutex, NULL) != 0)
5408
            return MEMORY_E;
5409
5410
        if (pthread_cond_init(&cond->cond, NULL) != 0) {
5411
            /* Keep compilers happy that we are using the return code */
5412
            if (pthread_mutex_destroy(&cond->mutex) != 0)
5413
                return MEMORY_E;
5414
            return MEMORY_E;
5415
        }
5416
    #endif
5417
        return 0;
5418
    }
5419
5420
    int wolfSSL_CondFree(COND_TYPE* cond)
5421
    {
5422
        if (cond == NULL)
5423
            return BAD_FUNC_ARG;
5424
    #if defined(__MACH__)
5425
        dispatch_release(cond->cond);
5426
    #elif defined(__OS2__)
5427
        DosCloseMutexSem(cond->mutex);
5428
        DosCloseEventSem(cond->cond);
5429
    #elif defined(__NT__)
5430
        if (CloseHandle(cond->cond) == 0)
5431
            return MEMORY_E;
5432
    #elif defined(__LINUX__)
5433
        if (pthread_mutex_destroy(&cond->mutex) != 0)
5434
            return MEMORY_E;
5435
5436
        if (pthread_cond_destroy(&cond->cond) != 0)
5437
            return MEMORY_E;
5438
    #endif
5439
        return 0;
5440
    }
5441
5442
    int wolfSSL_CondStart(COND_TYPE* cond)
5443
    {
5444
        if (cond == NULL)
5445
            return BAD_FUNC_ARG;
5446
    #if defined(__MACH__)
5447
    #elif defined(__OS2__)
5448
    #elif defined(__NT__)
5449
        if (wc_LockMutex(&cond->mutex) != 0)
5450
            return BAD_MUTEX_E;
5451
    #elif defined(__LINUX__)
5452
        if (pthread_mutex_lock(&cond->mutex) != 0)
5453
            return BAD_MUTEX_E;
5454
    #endif
5455
        return 0;
5456
    }
5457
5458
    int wolfSSL_CondSignal(COND_TYPE* cond)
5459
    {
5460
        if (cond == NULL)
5461
            return BAD_FUNC_ARG;
5462
    #if defined(__MACH__)
5463
        dispatch_semaphore_signal(cond->cond);
5464
    #elif defined(__OS2__)
5465
    #elif defined(__NT__)
5466
        if (wc_UnLockMutex(&cond->mutex) != 0)
5467
            return BAD_MUTEX_E;
5468
5469
        if (SetEvent(cond->cond) == 0)
5470
            return MEMORY_E;
5471
5472
        if (wc_LockMutex(&cond->mutex) != 0)
5473
            return BAD_MUTEX_E;
5474
    #elif defined(__LINUX__)
5475
        if (pthread_cond_signal(&cond->cond) != 0)
5476
            return MEMORY_E;
5477
    #endif
5478
        return 0;
5479
    }
5480
5481
    int wolfSSL_CondWait(COND_TYPE* cond)
5482
    {
5483
        if (cond == NULL)
5484
            return BAD_FUNC_ARG;
5485
    #if defined(__MACH__)
5486
        dispatch_semaphore_wait(cond->cond, DISPATCH_TIME_FOREVER);
5487
    #elif defined(__OS2__)
5488
    #elif defined(__NT__)
5489
        if (wc_UnLockMutex(&cond->mutex) != 0)
5490
            return BAD_MUTEX_E;
5491
5492
        if (WaitForSingleObject(cond->cond, INFINITE) == WAIT_FAILED)
5493
            return MEMORY_E;
5494
5495
        if (wc_LockMutex(&cond->mutex) != 0)
5496
            return BAD_MUTEX_E;
5497
    #elif defined(__LINUX__)
5498
        if (pthread_cond_wait(&cond->cond, &cond->mutex) != 0)
5499
            return MEMORY_E;
5500
    #endif
5501
        return 0;
5502
    }
5503
5504
    int wolfSSL_CondEnd(COND_TYPE* cond)
5505
    {
5506
        if (cond == NULL)
5507
            return BAD_FUNC_ARG;
5508
    #if defined(__OS2__)
5509
    #elif defined(__NT__)
5510
        if (wc_UnLockMutex(&cond->mutex) != 0)
5511
            return BAD_MUTEX_E;
5512
    #elif defined(__LINUX__)
5513
        if (pthread_mutex_unlock(&cond->mutex) != 0)
5514
            return BAD_MUTEX_E;
5515
    #endif
5516
        return 0;
5517
    }
5518
    #endif /* WOLFSSL_COND */
5519
5520
5521
#elif defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS) && \
5522
    !defined(_WIN32_WCE)
5523
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5524
        THREAD_CB cb, void* arg)
5525
    {
5526
        if (thread == NULL || cb == NULL)
5527
            return BAD_FUNC_ARG;
5528
5529
        /* Use _beginthreadex instead of _beginthread because of:
5530
         *   _beginthreadex is safer to use than _beginthread. If the thread
5531
         *   that's generated by _beginthread exits quickly, the handle that's
5532
         *   returned to the caller of _beginthread might be invalid or point
5533
         *   to another thread. However, the handle that's returned by
5534
         *   _beginthreadex has to be closed by the caller of _beginthreadex,
5535
         *   so it's guaranteed to be a valid handle if _beginthreadex didn't
5536
         *   return an error.*/
5537
        *thread = _beginthreadex(NULL, 0, cb, arg, 0, NULL);
5538
        if (*thread == 0) {
5539
            *thread = INVALID_THREAD_VAL;
5540
            return MEMORY_E;
5541
        }
5542
5543
        return 0;
5544
    }
5545
5546
#ifdef WOLFSSL_THREAD_NO_JOIN
5547
    int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg)
5548
    {
5549
        THREAD_TYPE thread;
5550
5551
        if (cb == NULL)
5552
            return BAD_FUNC_ARG;
5553
5554
        thread = _beginthread(cb, 0, arg);
5555
        if (thread == -1L) {
5556
            return MEMORY_E;
5557
        }
5558
5559
        return 0;
5560
    }
5561
#endif
5562
5563
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5564
    {
5565
        int ret = 0;
5566
5567
        if (thread == INVALID_THREAD_VAL)
5568
            return BAD_FUNC_ARG;
5569
5570
        /* We still want to attempt to close the thread handle even on error */
5571
        if (WaitForSingleObject((HANDLE)thread, INFINITE) == WAIT_FAILED)
5572
            ret = MEMORY_E;
5573
5574
        if (CloseHandle((HANDLE)thread) == 0)
5575
            ret = MEMORY_E;
5576
5577
        return ret;
5578
    }
5579
5580
#ifdef WOLFSSL_COND
5581
    int wolfSSL_CondInit(COND_TYPE* cond)
5582
    {
5583
        if (cond == NULL)
5584
            return BAD_FUNC_ARG;
5585
5586
        cond->cond = CreateEventA(NULL, FALSE, FALSE, NULL);
5587
        if (cond->cond == NULL)
5588
            return MEMORY_E;
5589
5590
        if (wc_InitMutex(&cond->mutex) != 0) {
5591
            if (CloseHandle(cond->cond) == 0)
5592
                return MEMORY_E;
5593
            return MEMORY_E;
5594
        }
5595
5596
        return 0;
5597
    }
5598
5599
    int wolfSSL_CondFree(COND_TYPE* cond)
5600
    {
5601
        if (cond == NULL)
5602
            return BAD_FUNC_ARG;
5603
5604
        if (CloseHandle(cond->cond) == 0)
5605
            return MEMORY_E;
5606
5607
        return 0;
5608
    }
5609
5610
    int wolfSSL_CondStart(COND_TYPE* cond)
5611
    {
5612
        if (cond == NULL)
5613
            return BAD_FUNC_ARG;
5614
5615
        if (wc_LockMutex(&cond->mutex) != 0)
5616
            return BAD_MUTEX_E;
5617
5618
        return 0;
5619
    }
5620
5621
    int wolfSSL_CondSignal(COND_TYPE* cond)
5622
    {
5623
        if (cond == NULL)
5624
            return BAD_FUNC_ARG;
5625
5626
        if (wc_UnLockMutex(&cond->mutex) != 0)
5627
            return BAD_MUTEX_E;
5628
5629
        if (SetEvent(cond->cond) == 0)
5630
            return MEMORY_E;
5631
5632
        if (wc_LockMutex(&cond->mutex) != 0)
5633
            return BAD_MUTEX_E;
5634
5635
        return 0;
5636
    }
5637
5638
    int wolfSSL_CondWait(COND_TYPE* cond)
5639
    {
5640
        if (cond == NULL)
5641
            return BAD_FUNC_ARG;
5642
5643
        if (wc_UnLockMutex(&cond->mutex) != 0)
5644
            return BAD_MUTEX_E;
5645
5646
        if (WaitForSingleObject(cond->cond, INFINITE) == WAIT_FAILED)
5647
            return MEMORY_E;
5648
5649
        if (wc_LockMutex(&cond->mutex) != 0)
5650
            return BAD_MUTEX_E;
5651
5652
        return 0;
5653
    }
5654
5655
    int wolfSSL_CondEnd(COND_TYPE* cond)
5656
    {
5657
        if (cond == NULL)
5658
            return BAD_FUNC_ARG;
5659
5660
        if (wc_UnLockMutex(&cond->mutex) != 0)
5661
            return BAD_MUTEX_E;
5662
5663
        return 0;
5664
    }
5665
#endif /* WOLFSSL_COND */
5666
5667
#elif defined(WOLFSSL_TIRTOS)
5668
5669
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5670
        THREAD_CB cb, void* arg)
5671
    {
5672
        /* Initialize the defaults and set the parameters. */
5673
        Task_Params taskParams;
5674
        Task_Params_init(&taskParams);
5675
        taskParams.arg0 = (UArg)arg;
5676
        taskParams.stackSize = 65535;
5677
        *thread = Task_create((Task_FuncPtr)cb, &taskParams, NULL);
5678
        if (*thread == NULL) {
5679
            return MEMORY_E;
5680
        }
5681
        Task_yield();
5682
        return 0;
5683
    }
5684
5685
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5686
    {
5687
        while(1) {
5688
            if (Task_getMode(thread) == Task_Mode_TERMINATED) {
5689
                Task_sleep(5);
5690
                break;
5691
            }
5692
            Task_yield();
5693
        }
5694
        return 0;
5695
    }
5696
5697
#elif defined(NETOS)
5698
5699
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5700
        THREAD_CB cb, void* arg)
5701
    {
5702
        /* For backwards compatibility allow using this declaration as well. */
5703
        #ifdef TESTSUITE_THREAD_STACK_SZ
5704
            #define WOLFSSL_NETOS_STACK_SZ TESTSUITE_THREAD_STACK_SZ
5705
        #endif
5706
        /* This can be adjusted by defining in user_settings.h, will default to
5707
         * 65k in the event it is undefined */
5708
        #ifndef WOLFSSL_NETOS_STACK_SZ
5709
            #define WOLFSSL_NETOS_STACK_SZ 65535
5710
        #endif
5711
        int result;
5712
5713
        if (thread == NULL || cb == NULL)
5714
            return BAD_FUNC_ARG;
5715
5716
        XMEMSET(thread, 0, sizeof(*thread));
5717
5718
        thread->tid = (TX_THREAD *)XMALLOC(sizeof(TX_THREAD), NULL,
5719
                DYNAMIC_TYPE_OS_BUF);
5720
        if (thread->tid == NULL)
5721
            return MEMORY_E;
5722
        XMEMSET(thread->tid, 0, sizeof(TX_THREAD));
5723
5724
        thread->threadStack = (void *)XMALLOC(WOLFSSL_NETOS_STACK_SZ, NULL,
5725
                DYNAMIC_TYPE_OS_BUF);
5726
        if (thread->threadStack == NULL) {
5727
            XFREE(thread->tid, NULL, DYNAMIC_TYPE_OS_BUF);
5728
            thread->tid = NULL;
5729
            return MEMORY_E;
5730
        }
5731
5732
        /* first create the idle thread:
5733
         * ARGS:
5734
         * Param1: pointer to thread
5735
         * Param2: name
5736
         * Param3 and 4: entry function and input
5737
         * Param5: pointer to thread stack
5738
         * Param6: stack size
5739
         * Param7 and 8: priority level and preempt threshold
5740
         * Param9 and 10: time slice and auto-start indicator */
5741
        result = tx_thread_create(thread->tid,
5742
                           "wolfSSL thread",
5743
                           (entry_functionType)cb, (ULONG)arg,
5744
                           thread->threadStack,
5745
                           WOLFSSL_NETOS_STACK_SZ,
5746
                           2, 2,
5747
                           1, TX_AUTO_START);
5748
        if (result != TX_SUCCESS) {
5749
            XFREE(thread->threadStack, NULL, DYNAMIC_TYPE_OS_BUF);
5750
            thread->threadStack = NULL;
5751
            XFREE(thread->tid, NULL, DYNAMIC_TYPE_OS_BUF);
5752
            thread->tid = NULL;
5753
            return MEMORY_E;
5754
        }
5755
5756
        return 0;
5757
    }
5758
5759
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5760
    {
5761
        UINT state = TX_READY;
5762
        int ret = 0;
5763
5764
        if (thread.tid == NULL)
5765
            return BAD_FUNC_ARG;
5766
5767
        /* The thread runs on threadStack, so it has to be done with it before
5768
         * the stack is released. Wait for the entry function to return, or for
5769
         * the thread to be terminated by someone else. */
5770
        while (ret == 0 && state != TX_COMPLETED && state != TX_TERMINATED) {
5771
            if (tx_thread_info_get(thread.tid, TX_NULL, &state, TX_NULL,
5772
                        TX_NULL, TX_NULL, TX_NULL, TX_NULL, TX_NULL)
5773
                    != TX_SUCCESS) {
5774
                /* The control block is not a thread ThreadX knows about, so
5775
                 * nothing is running on the stack either. */
5776
                ret = BAD_STATE_E;
5777
            }
5778
            else if (state != TX_COMPLETED && state != TX_TERMINATED) {
5779
                tx_thread_sleep(1);
5780
            }
5781
        }
5782
5783
        /* Unregister the thread before its control block and stack go away. */
5784
        if (ret == 0 && tx_thread_delete(thread.tid) != TX_SUCCESS) {
5785
            /* ThreadX still owns the control block and the thread may still be
5786
             * running on the stack, so neither can be released here. */
5787
            WOLFSSL_MSG("tx_thread_delete failed, leaking thread resources");
5788
            return BAD_STATE_E;
5789
        }
5790
5791
        XFREE(thread.threadStack, NULL, DYNAMIC_TYPE_OS_BUF);
5792
        thread.threadStack = NULL;
5793
        XFREE(thread.tid, NULL, DYNAMIC_TYPE_OS_BUF);
5794
        thread.tid = NULL;
5795
5796
        return ret;
5797
    }
5798
5799
#elif defined(WOLFSSL_ZEPHYR)
5800
5801
    void* wolfsslThreadHeapHint = NULL;
5802
5803
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5804
        THREAD_CB cb, void* arg)
5805
    {
5806
        #ifndef WOLFSSL_ZEPHYR_STACK_SZ
5807
            #define WOLFSSL_ZEPHYR_STACK_SZ (48*1024)
5808
        #endif
5809
5810
        if (thread == NULL || cb == NULL)
5811
            return BAD_FUNC_ARG;
5812
5813
        XMEMSET(thread, 0, sizeof(*thread));
5814
5815
        thread->tid = (struct k_thread*)XMALLOC(
5816
                Z_KERNEL_STACK_SIZE_ADJUST(sizeof(struct k_thread)),
5817
                wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER);
5818
        if (thread->tid == NULL) {
5819
            WOLFSSL_MSG("error: XMALLOC thread->tid failed");
5820
            return MEMORY_E;
5821
        }
5822
5823
        /* TODO: Use the following once k_thread_stack_alloc makes it into a
5824
         * release.
5825
         * thread->threadStack = k_thread_stack_alloc(WOLFSSL_ZEPHYR_STACK_SZ,
5826
         *                                            0);
5827
         */
5828
        thread->threadStack = (void*)XMALLOC(
5829
                Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ),
5830
                wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER);
5831
        if (thread->threadStack == NULL) {
5832
            XFREE(thread->tid, wolfsslThreadHeapHint,
5833
                    DYNAMIC_TYPE_TMP_BUFFER);
5834
            thread->tid = NULL;
5835
5836
            WOLFSSL_MSG("error: XMALLOC thread->threadStack failed");
5837
            return MEMORY_E;
5838
        }
5839
5840
        /* k_thread_create does not return any error codes */
5841
        /* Casting to k_thread_entry_t should be fine since we just ignore the
5842
         * extra arguments being passed in */
5843
        k_thread_create(thread->tid, thread->threadStack,
5844
                WOLFSSL_ZEPHYR_STACK_SZ, (k_thread_entry_t)cb, arg, NULL, NULL,
5845
                5, 0, K_NO_WAIT);
5846
5847
        return 0;
5848
    }
5849
5850
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5851
    {
5852
        int ret = 0;
5853
        int err;
5854
5855
        err = k_thread_join(thread.tid, K_FOREVER);
5856
        if (err != 0)
5857
            ret = MEMORY_E;
5858
5859
        XFREE(thread.tid, wolfsslThreadHeapHint,
5860
                DYNAMIC_TYPE_TMP_BUFFER);
5861
        thread.tid = NULL;
5862
5863
        /* TODO: Use the following once k_thread_stack_free makes it into a
5864
         * release.
5865
         * err = k_thread_stack_free(thread.threadStack);
5866
         * if (err != 0)
5867
         *     ret = MEMORY_E;
5868
         */
5869
        XFREE(thread.threadStack, wolfsslThreadHeapHint,
5870
                DYNAMIC_TYPE_TMP_BUFFER);
5871
        thread.threadStack = NULL;
5872
5873
        /* No thread resources to free. Everything is stored in thread.tid */
5874
5875
        return ret;
5876
    }
5877
5878
#ifdef WOLFSSL_COND
5879
    /* Native Zephyr condition variables (k_condvar) over a k_mutex; no POSIX
5880
     * pthread layer required. Semantics mirror the pthread implementation. */
5881
    int wolfSSL_CondInit(COND_TYPE* cond)
5882
    {
5883
        int ret;
5884
5885
        if (cond == NULL)
5886
            return BAD_FUNC_ARG;
5887
5888
        ret = wc_InitMutex(&cond->mutex);
5889
        if (ret == 0) {
5890
            /* k_condvar_init always returns 0 on Zephyr. */
5891
            (void)k_condvar_init(&cond->cond);
5892
        }
5893
5894
        return ret;
5895
    }
5896
5897
    int wolfSSL_CondFree(COND_TYPE* cond)
5898
    {
5899
        if (cond == NULL)
5900
            return BAD_FUNC_ARG;
5901
5902
        /* k_condvar has no destroy; just release the backing mutex. */
5903
        return wc_FreeMutex(&cond->mutex);
5904
    }
5905
5906
    int wolfSSL_CondStart(COND_TYPE* cond)
5907
    {
5908
        if (cond == NULL)
5909
            return BAD_FUNC_ARG;
5910
5911
        if (wc_LockMutex(&cond->mutex) != 0)
5912
            return BAD_MUTEX_E;
5913
5914
        return 0;
5915
    }
5916
5917
    int wolfSSL_CondSignal(COND_TYPE* cond)
5918
    {
5919
        if (cond == NULL)
5920
            return BAD_FUNC_ARG;
5921
5922
        /* Caller holds cond->mutex; wake a single waiter. */
5923
        (void)k_condvar_signal(&cond->cond);
5924
5925
        return 0;
5926
    }
5927
5928
    int wolfSSL_CondWait(COND_TYPE* cond)
5929
    {
5930
        if (cond == NULL)
5931
            return BAD_FUNC_ARG;
5932
5933
        /* Atomically releases the mutex, blocks, and re-acquires it on wake,
5934
         * matching pthread_cond_wait semantics. */
5935
        if (k_condvar_wait(&cond->cond, &cond->mutex, K_FOREVER) != 0)
5936
            return BAD_MUTEX_E;
5937
5938
        return 0;
5939
    }
5940
5941
    int wolfSSL_CondEnd(COND_TYPE* cond)
5942
    {
5943
        if (cond == NULL)
5944
            return BAD_FUNC_ARG;
5945
5946
        if (wc_UnLockMutex(&cond->mutex) != 0)
5947
            return BAD_MUTEX_E;
5948
5949
        return 0;
5950
    }
5951
#endif /* WOLFSSL_COND */
5952
5953
#elif defined(WOLFSSL_PTHREADS) || \
5954
     (defined(FREERTOS) && defined(WOLFSSL_ESPIDF))
5955
5956
    int wolfSSL_NewThread(THREAD_TYPE* thread,
5957
        THREAD_CB cb, void* arg)
5958
0
    {
5959
0
        if (thread == NULL || cb == NULL)
5960
0
            return BAD_FUNC_ARG;
5961
5962
0
        if (pthread_create(thread, NULL, cb, arg) != 0)
5963
0
            return MEMORY_E;
5964
5965
0
        return 0;
5966
0
    }
5967
5968
    #ifdef WOLFSSL_THREAD_NO_JOIN
5969
        int wolfSSL_NewThreadNoJoin(THREAD_CB_NOJOIN cb, void* arg)
5970
0
        {
5971
0
            THREAD_TYPE thread;
5972
0
            int ret;
5973
0
            XMEMSET(&thread, 0, sizeof(thread));
5974
0
            ret = wolfSSL_NewThread(&thread, cb, arg);
5975
0
            if (ret == 0)
5976
0
                ret = pthread_detach(thread);
5977
0
            return ret;
5978
0
        }
5979
    #endif
5980
5981
    int wolfSSL_JoinThread(THREAD_TYPE thread)
5982
0
    {
5983
0
        if (thread == INVALID_THREAD_VAL)
5984
0
            return BAD_FUNC_ARG;
5985
5986
0
        if (pthread_join(thread, NULL) != 0)
5987
0
            return MEMORY_E;
5988
5989
0
        return 0;
5990
0
    }
5991
5992
#ifdef WOLFSSL_COND
5993
    #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 \
5994
        && !defined(__ppc__)
5995
    /* Apple style dispatch semaphore */
5996
    int wolfSSL_CondInit(COND_TYPE* cond)
5997
    {
5998
        if (cond == NULL)
5999
            return BAD_FUNC_ARG;
6000
6001
        /* dispatch_release() fails hard, with Trace/BPT trap signal, if the
6002
         * sem's internal count is less than the value passed in with
6003
         * dispatch_semaphore_create().  work around this by initing
6004
         * with 0, then incrementing it afterwards.
6005
         */
6006
        cond->cond = dispatch_semaphore_create(0);
6007
        if (cond->cond == NULL)
6008
            return MEMORY_E;
6009
6010
        if (wc_InitMutex(&cond->mutex) != 0) {
6011
            dispatch_release(cond->cond);
6012
            return MEMORY_E;
6013
        }
6014
6015
        return 0;
6016
    }
6017
6018
    int wolfSSL_CondFree(COND_TYPE* cond)
6019
    {
6020
        if (cond == NULL)
6021
            return BAD_FUNC_ARG;
6022
6023
        dispatch_release(cond->cond);
6024
        cond->cond = NULL;
6025
6026
        if (wc_FreeMutex(&cond->mutex) != 0) {
6027
            return MEMORY_E;
6028
        }
6029
6030
        return 0;
6031
    }
6032
6033
    int wolfSSL_CondStart(COND_TYPE* cond)
6034
    {
6035
        if (cond == NULL)
6036
            return BAD_FUNC_ARG;
6037
6038
        if (wc_LockMutex(&cond->mutex) != 0)
6039
            return BAD_MUTEX_E;
6040
6041
        return 0;
6042
    }
6043
6044
    int wolfSSL_CondSignal(COND_TYPE* cond)
6045
    {
6046
        if (cond == NULL)
6047
            return BAD_FUNC_ARG;
6048
6049
        if (wc_UnLockMutex(&cond->mutex) != 0)
6050
            return BAD_MUTEX_E;
6051
6052
        dispatch_semaphore_signal(cond->cond);
6053
6054
        if (wc_LockMutex(&cond->mutex) != 0)
6055
            return BAD_MUTEX_E;
6056
6057
        return 0;
6058
    }
6059
6060
    int wolfSSL_CondWait(COND_TYPE* cond)
6061
    {
6062
        if (cond == NULL)
6063
            return BAD_FUNC_ARG;
6064
6065
        if (wc_UnLockMutex(&cond->mutex) != 0)
6066
            return BAD_MUTEX_E;
6067
6068
        dispatch_semaphore_wait(cond->cond, DISPATCH_TIME_FOREVER);
6069
6070
        if (wc_LockMutex(&cond->mutex) != 0)
6071
            return BAD_MUTEX_E;
6072
6073
        return 0;
6074
    }
6075
6076
    int wolfSSL_CondEnd(COND_TYPE* cond)
6077
    {
6078
        if (cond == NULL)
6079
            return BAD_FUNC_ARG;
6080
6081
        if (wc_UnLockMutex(&cond->mutex) != 0)
6082
            return BAD_MUTEX_E;
6083
6084
        return 0;
6085
    }
6086
6087
    #else /* Generic POSIX conditional */
6088
6089
    int wolfSSL_CondInit(COND_TYPE* cond)
6090
0
    {
6091
0
        if (cond == NULL)
6092
0
            return BAD_FUNC_ARG;
6093
6094
0
        if (pthread_mutex_init(&cond->mutex, NULL) != 0)
6095
0
            return MEMORY_E;
6096
6097
0
        if (pthread_cond_init(&cond->cond, NULL) != 0) {
6098
            /* Keep compilers happy that we are using the return code */
6099
0
            if (pthread_mutex_destroy(&cond->mutex) != 0)
6100
0
                return MEMORY_E;
6101
0
            return MEMORY_E;
6102
0
        }
6103
6104
0
        return 0;
6105
0
    }
6106
6107
    int wolfSSL_CondFree(COND_TYPE* cond)
6108
0
    {
6109
0
        int ret = 0;
6110
6111
0
        if (cond == NULL)
6112
0
            return BAD_FUNC_ARG;
6113
6114
0
        if (pthread_mutex_destroy(&cond->mutex) != 0)
6115
0
            ret = MEMORY_E;
6116
6117
0
        if (pthread_cond_destroy(&cond->cond) != 0)
6118
0
            ret = MEMORY_E;
6119
6120
0
        return ret;
6121
0
    }
6122
6123
    int wolfSSL_CondStart(COND_TYPE* cond)
6124
0
    {
6125
0
        if (cond == NULL)
6126
0
            return BAD_FUNC_ARG;
6127
6128
0
        if (pthread_mutex_lock(&cond->mutex) != 0)
6129
0
            return BAD_MUTEX_E;
6130
6131
0
        return 0;
6132
0
    }
6133
6134
    int wolfSSL_CondSignal(COND_TYPE* cond)
6135
0
    {
6136
0
        if (cond == NULL)
6137
0
            return BAD_FUNC_ARG;
6138
6139
0
        if (pthread_cond_signal(&cond->cond) != 0)
6140
0
            return MEMORY_E;
6141
6142
0
        return 0;
6143
0
    }
6144
6145
    int wolfSSL_CondWait(COND_TYPE* cond)
6146
0
    {
6147
0
        if (cond == NULL)
6148
0
            return BAD_FUNC_ARG;
6149
6150
0
        if (pthread_cond_wait(&cond->cond, &cond->mutex) != 0)
6151
0
            return MEMORY_E;
6152
6153
0
        return 0;
6154
0
    }
6155
6156
    int wolfSSL_CondEnd(COND_TYPE* cond)
6157
0
    {
6158
0
        if (cond == NULL)
6159
0
            return BAD_FUNC_ARG;
6160
6161
0
        if (pthread_mutex_unlock(&cond->mutex) != 0)
6162
0
            return BAD_MUTEX_E;
6163
6164
0
        return 0;
6165
0
    }
6166
6167
    #endif /* __MACH__ */
6168
#endif /* WOLFSSL_COND */
6169
6170
#endif /* Environment check */
6171
6172
#endif /* not SINGLE_THREADED */
6173
6174
#if (defined(__unix__) || defined(__APPLE__)) && \
6175
    !defined(WOLFSSL_KERNEL_MODE) && !defined(WOLFSSL_ZEPHYR) && \
6176
    !defined(WOLFSSL_SGX) && !defined(WOLFSSL_OPTEE)
6177
6178
#include <fcntl.h>
6179
#include <errno.h>
6180
#include <sys/socket.h>
6181
#include <unistd.h>
6182
6183
#ifndef O_CLOEXEC
6184
    #define O_CLOEXEC 0
6185
#endif
6186
#ifndef SOCK_CLOEXEC
6187
    #define SOCK_CLOEXEC 0
6188
#endif
6189
6190
/* accept4(): HAVE_ACCEPT4 is set by the configure/CMake probe, or in
6191
 * user_settings.h for a libc not recognised here, such as musl. Recognised:
6192
 * glibc 2.10, uClibc-ng, bionic API 21, FreeBSD 10. */
6193
#if (defined(__linux__) || defined(__ANDROID__)) && \
6194
    (defined(HAVE_ACCEPT4) || \
6195
     (defined(__USE_GNU) && \
6196
      ((defined(__GLIBC__) && \
6197
        (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10))) || \
6198
       (defined(__UCLIBC_LINUX_SPECIFIC__) && (__UCLIBC_MAJOR__ >= 1)) || \
6199
       (defined(__ANDROID_API__) && (__ANDROID_API__ >= 21)))))
6200
    #define WC_HAVE_ACCEPT4
6201
#elif defined(__FreeBSD__) && defined(__BSD_VISIBLE) && __BSD_VISIBLE && \
6202
    (__FreeBSD_version >= 1000000)
6203
    #define WC_HAVE_ACCEPT4
6204
#endif
6205
6206
void wc_set_cloexec(int fd)
6207
0
{
6208
0
#ifdef FD_CLOEXEC
6209
0
    int fdFlags;
6210
0
    if (fd < 0)
6211
0
        return;
6212
0
    fdFlags = fcntl(fd, F_GETFD);
6213
0
    if (fdFlags >= 0)
6214
0
        (void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC);
6215
#else
6216
    (void)fd;
6217
#endif
6218
0
}
6219
6220
int wc_open_cloexec(const char* path, int flags)
6221
0
{
6222
0
    int fd = open(path, flags | O_CLOEXEC);
6223
0
#ifdef FD_CLOEXEC
6224
0
    if (fd < 0 && errno == EINVAL) {
6225
0
        fd = open(path, flags);
6226
0
        wc_set_cloexec(fd);
6227
0
    }
6228
0
#endif
6229
0
    return fd;
6230
0
}
6231
6232
/* As wc_open_cloexec(), for flags with O_CREAT, where open() needs a mode. */
6233
int wc_open_cloexec_mode(const char* path, int flags, int mode)
6234
0
{
6235
0
    int fd = open(path, flags | O_CLOEXEC, mode);
6236
0
#ifdef FD_CLOEXEC
6237
0
    if (fd < 0 && errno == EINVAL) {
6238
0
        fd = open(path, flags, mode);
6239
0
        wc_set_cloexec(fd);
6240
0
    }
6241
0
#endif
6242
0
    return fd;
6243
0
}
6244
6245
#if !defined(NO_FILESYSTEM) && defined(XFDOPEN)
6246
#include <sys/stat.h>
6247
6248
/* Truncate or create path for writing, owner read/write only. */
6249
XFILE wc_fopen_owner_only(const char* path)
6250
0
{
6251
0
    XFILE file;
6252
0
    int fd = wc_open_cloexec_mode(path, O_RDWR | O_CREAT | O_TRUNC,
6253
0
                                  S_IRUSR | S_IWUSR);
6254
0
    if (fd < 0)
6255
0
        return XBADFILE;
6256
6257
0
#ifndef WOLFSSL_NO_FCHMOD
6258
0
    if (fchmod(fd, S_IRUSR | S_IWUSR) != 0) {
6259
0
        close(fd);
6260
0
        return XBADFILE;
6261
0
    }
6262
0
#endif
6263
6264
0
    file = XFDOPEN(fd, "w+b");
6265
0
    if (file == XBADFILE)
6266
0
        close(fd);
6267
6268
0
    return file;
6269
0
}
6270
#endif /* !NO_FILESYSTEM && XFDOPEN */
6271
6272
int wc_socket_cloexec(int domain, int type, int protocol)
6273
0
{
6274
0
    int fd = socket(domain, type | SOCK_CLOEXEC, protocol);
6275
0
#ifdef FD_CLOEXEC
6276
0
    if (fd < 0 && errno == EINVAL) {
6277
0
        fd = socket(domain, type, protocol);
6278
0
        wc_set_cloexec(fd);
6279
0
    }
6280
0
#endif
6281
0
    return fd;
6282
0
}
6283
6284
int wc_accept_cloexec(int sockfd, void* addr, void* addrlen)
6285
0
{
6286
0
    int fd;
6287
0
#ifdef WC_HAVE_ACCEPT4
6288
0
    fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen,
6289
0
                 SOCK_CLOEXEC);
6290
0
    if (fd >= 0)
6291
0
        return fd;
6292
0
    if (errno != ENOSYS && errno != EINVAL)
6293
0
        return fd;
6294
0
#endif
6295
0
    fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
6296
0
    wc_set_cloexec(fd);
6297
0
    return fd;
6298
0
}
6299
6300
#endif /* (__unix__ || __APPLE__) && !WOLFSSL_KERNEL_MODE && !WOLFSSL_ZEPHYR &&
6301
        * !WOLFSSL_SGX */
6302
6303
#if defined(WOLFSSL_LINUXKM) && defined(CONFIG_ARM64) && \
6304
    defined(WC_SYM_RELOC_TABLES)
6305
#ifndef CONFIG_ARCH_TEGRA
6306
6307
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
6308
noinstr void my__alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr,
6309
                                   __le32 *updptr, int nr_inst)
6310
{
6311
    return WC_PIE_INDIRECT_SYM(alt_cb_patch_nops)
6312
        (alt, origptr, updptr, nr_inst);
6313
}
6314
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) */
6315
6316
void my__queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
6317
{
6318
    return WC_PIE_INDIRECT_SYM(queued_spin_lock_slowpath)
6319
        (lock, val);
6320
}
6321
#endif
6322
#endif