Coverage Report

Created: 2026-08-14 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/wolfcrypt/src/memory.c
Line
Count
Source
1
/* memory.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
/* inhibit "#undef current" in linuxkm_wc_port.h, included from wc_port.h,
23
 * because needed in linuxkm_memory.c, included below.
24
 */
25
#ifdef WOLFSSL_LINUXKM
26
    #define WOLFSSL_LINUXKM_NEED_LINUX_CURRENT
27
#endif
28
29
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
30
31
#ifdef NO_INLINE
32
    #include <wolfssl/wolfcrypt/misc.h>
33
#else
34
    #define WOLFSSL_MISC_INCLUDED
35
    #include <wolfcrypt/src/misc.c>
36
#endif
37
38
/*
39
Possible memory options:
40
 * NO_WOLFSSL_MEMORY:               Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY.
41
 * WOLFSSL_STATIC_MEMORY:           Turns on the use of static memory buffers and functions.
42
                                        This allows for using static memory instead of dynamic.
43
 * WOLFSSL_STATIC_MEMORY_LEAN:      Requires WOLFSSL_STATIC_MEMORY be defined.
44
 *                                  Uses smaller type sizes for structs
45
 *                                  requiring that memory pool sizes be less
46
 *                                  then 65k and limits features available like
47
 *                                  IO buffers to reduce footprint size.
48
 * WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK:
49
 *                                  Enables option to register a debugging
50
 *                                  callback function, useful for
51
 *                                  WOLFSSL_STATIC_MEMORY builds where XMALLOC
52
 *                                  and XFREE are not user defined.
53
 * WOLFSSL_STATIC_ALIGN:            Define defaults to 16 to indicate static memory alignment.
54
 * HAVE_IO_POOL:                    Enables use of static thread safe memory pool for input/output buffers.
55
 * XMALLOC_OVERRIDE:                Allows override of the XMALLOC, XFREE and XREALLOC macros.
56
 * XMALLOC_USER:                    Allows custom XMALLOC, XFREE and XREALLOC functions to be defined.
57
 * WOLFSSL_NO_MALLOC:               Disables the fall-back case to use STDIO malloc/free when no callbacks are set.
58
 * WOLFSSL_TRACK_MEMORY:            Enables memory tracking for total stats and list of allocated memory.
59
 * WOLFSSL_DEBUG_MEMORY:            Enables extra function and line number args for memory callbacks.
60
 * WOLFSSL_DEBUG_MEMORY_PRINT:      Enables printing of each malloc/free.
61
 * WOLFSSL_MALLOC_CHECK:            Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
62
 * WOLFSSL_FORCE_MALLOC_FAIL_TEST:  Used for internal testing to induce random malloc failures.
63
 * WOLFSSL_HEAP_TEST:               Used for internal testing of heap hint
64
 * WOLFSSL_MEM_FAIL_COUNT:          Fail memory allocation at a count from
65
 *                                  environment variable: MEM_FAIL_CNT.
66
 */
67
68
#ifdef WOLFSSL_ZEPHYR
69
#undef realloc
70
void *z_realloc(void *ptr, size_t size)
71
{
72
    if (ptr == NULL)
73
        ptr = malloc(size); /* native heap */
74
    else
75
        ptr = realloc(ptr, size); /* native heap */
76
77
    return ptr;
78
}
79
#define realloc z_realloc
80
#endif
81
82
#ifdef USE_WOLFSSL_MEMORY
83
84
#include <wolfssl/wolfcrypt/memory.h>
85
86
#if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT)
87
#include <stdio.h>
88
#endif
89
90
#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
91
    static int gMemFailCountSeed;
92
    static int gMemFailCount;
93
    void wolfSSL_SetMemFailCount(int memFailCount)
94
    {
95
        if (gMemFailCountSeed == 0) {
96
            gMemFailCountSeed = memFailCount;
97
            gMemFailCount = memFailCount;
98
        }
99
    }
100
#endif
101
#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \
102
                                                     defined(WOLFSSL_MEMORY_LOG)
103
    #include <stdio.h>
104
#endif
105
106
107
/* Set these to default values initially. */
108
static wolfSSL_Malloc_cb  malloc_function = NULL;
109
static wolfSSL_Free_cb    free_function = NULL;
110
static wolfSSL_Realloc_cb realloc_function = NULL;
111
112
int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
113
                          wolfSSL_Free_cb    ff,
114
                          wolfSSL_Realloc_cb rf)
115
0
{
116
0
    malloc_function = mf;
117
0
    free_function = ff;
118
0
    realloc_function = rf;
119
0
    return 0;
120
0
}
121
122
int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
123
                          wolfSSL_Free_cb*    ff,
124
                          wolfSSL_Realloc_cb* rf)
125
0
{
126
0
    if (mf) *mf = malloc_function;
127
0
    if (ff) *ff = free_function;
128
0
    if (rf) *rf = realloc_function;
129
0
    return 0;
130
0
}
131
132
#ifdef WOLFSSL_MEM_FAIL_COUNT
133
static wolfSSL_Mutex memFailMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(memFailMutex);
134
int mem_fail_allocs = 0;
135
int mem_fail_frees = 0;
136
int mem_fail_cnt = 0;
137
138
void wc_MemFailCount_Init(void)
139
{
140
    char* cnt;
141
#ifndef WOLFSSL_MUTEX_INITIALIZER
142
    wc_InitMutex(&memFailMutex);
143
#endif
144
    cnt = getenv("MEM_FAIL_CNT");
145
    if (cnt != NULL) {
146
        fprintf(stderr, "MemFailCount At: %d\n", mem_fail_cnt);
147
        mem_fail_cnt = atoi(cnt);
148
    }
149
}
150
static int wc_MemFailCount_AllocMem(void)
151
{
152
    int ret = 1;
153
154
    wc_LockMutex(&memFailMutex);
155
    if ((mem_fail_cnt > 0) && (mem_fail_cnt <= mem_fail_allocs + 1)) {
156
        ret = 0;
157
    }
158
    else {
159
        mem_fail_allocs++;
160
    }
161
    wc_UnLockMutex(&memFailMutex);
162
163
    return ret;
164
}
165
static void wc_MemFailCount_FreeMem(void)
166
{
167
    wc_LockMutex(&memFailMutex);
168
    mem_fail_frees++;
169
    wc_UnLockMutex(&memFailMutex);
170
}
171
void wc_MemFailCount_Free(void)
172
{
173
#ifndef WOLFSSL_MUTEX_INITIALIZER
174
    wc_FreeMutex(&memFailMutex);
175
#endif
176
    fprintf(stderr, "MemFailCount Total: %d\n", mem_fail_allocs);
177
    fprintf(stderr, "MemFailCount Frees: %d\n", mem_fail_frees);
178
}
179
#endif
180
181
#ifndef WOLFSSL_STATIC_MEMORY
182
#ifdef WOLFSSL_CHECK_MEM_ZERO
183
184
#ifndef WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN
185
/* Number of entries in table of addresses to check. */
186
#define WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN    256
187
#endif
188
189
/* Alignment to maintain when adding length to allocated pointer.
190
 * Intel x64 wants to use aligned loads of XMM registers.
191
 */
192
#define MEM_ALIGN       16
193
194
/* An address that is meant to be all zeros for its length. */
195
typedef struct MemZero {
196
    /* Name of address to check. */
197
    const char* name;
198
    /* Address to check. */
199
    const void* addr;
200
    /* Length of data that must be zero. */
201
    size_t len;
202
} MemZero;
203
204
/* List of addresses to check. */
205
static MemZero memZero[WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN];
206
/* Next index to place address at.
207
 * -1 indicates uninitialized.
208
 * If nextIdx is equal to WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN then all entries
209
 * have been used.
210
 */
211
static int nextIdx = -1;
212
/* Mutex to protect modifying list of addresses to check. */
213
static wolfSSL_Mutex zeroMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(zeroMutex);
214
215
/* Initialize the table of addresses and the mutex.
216
 */
217
void wc_MemZero_Init(void)
218
{
219
    /* Clear the table to more easily see what is valid. */
220
    XMEMSET(memZero, 0, sizeof(memZero));
221
    /* Initialize mutex. */
222
#ifndef WOLFSSL_MUTEX_INITIALIZER
223
    wc_InitMutex(&zeroMutex);
224
#endif
225
    /* Next index is first entry. */
226
    nextIdx = 0;
227
}
228
229
/* Free the mutex and check we have not any uncheck addresses.
230
 */
231
void wc_MemZero_Free(void)
232
{
233
    /* Free mutex. */
234
#ifndef WOLFSSL_MUTEX_INITIALIZER
235
    wc_FreeMutex(&zeroMutex);
236
#endif
237
    /* Make sure we checked all addresses. */
238
    if (nextIdx > 0) {
239
        int i;
240
        fprintf(stderr, "[MEM_ZERO] Unseen: %d\n", nextIdx);
241
        for (i = 0; i < nextIdx; i++) {
242
            fprintf(stderr, "  %s - %p:%lu\n", memZero[i].name, memZero[i].addr,
243
                (unsigned long)memZero[i].len);
244
        }
245
    }
246
    /* Uninitialized value in next index. */
247
    nextIdx = -1;
248
}
249
250
/* Add an address to check.
251
 *
252
 * @param [in] name  Name of address to check.
253
 * @param [in] addr  Address that needs to be checked.
254
 * @param [in] len   Length of data that must be zero.
255
 */
256
void wc_MemZero_Add(const char* name, const void* addr, size_t len)
257
{
258
    /* Initialize if not done. */
259
    if (nextIdx == -1) {
260
        wc_MemZero_Init();
261
    }
262
263
    /* Add an entry to the table while locked. */
264
    wc_LockMutex(&zeroMutex);
265
    if (nextIdx < WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN) {
266
        /* Fill in the next entry and update next index. */
267
        memZero[nextIdx].name = name;
268
        memZero[nextIdx].addr = addr;
269
        memZero[nextIdx].len  = len;
270
        nextIdx++;
271
    }
272
    else {
273
        /* Abort when too many entries. */
274
        fprintf(stderr, "\n[MEM_ZERO] Too many addresses to check\n");
275
        fprintf(stderr, "[MEM_ZERO] WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN\n");
276
        abort();
277
    }
278
    wc_UnLockMutex(&zeroMutex);
279
}
280
281
/* Check the memory in the range of the address for memory that must be zero.
282
 *
283
 * @param [in] addr  Start address of memory that is to be checked.
284
 * @param [in] len   Length of data associated with address.
285
 */
286
void wc_MemZero_Check(void* addr, size_t len)
287
{
288
    int i;
289
    size_t j;
290
291
    wc_LockMutex(&zeroMutex);
292
    /* Look at each address for overlap with address passes in. */
293
    for (i = 0; i < nextIdx; i++) {
294
        if ((memZero[i].addr < addr) ||
295
               ((size_t)memZero[i].addr >= (size_t)addr + len)) {
296
            /* Check address not part of memory to check. */
297
            continue;
298
        }
299
300
        /* Address is in range of memory being freed - check each byte zero. */
301
        for (j = 0; j < memZero[i].len; j++) {
302
            if (((unsigned char*)memZero[i].addr)[j] != 0) {
303
                /* Byte not zero - abort! */
304
                fprintf(stderr, "\n[MEM_ZERO] %s:%p + %lu is not zero\n",
305
                    memZero[i].name, memZero[i].addr, (unsigned long)j);
306
                fprintf(stderr, "[MEM_ZERO] Checking %p:%lu\n", addr,
307
                    (unsigned long)len);
308
            #ifndef TEST_ALWAYS_RUN_TO_END
309
                abort();
310
            #endif
311
            }
312
        }
313
        /* Update next index to write to. */
314
        nextIdx--;
315
        if (nextIdx > 0) {
316
            /* Remove entry. */
317
            XMEMMOVE(memZero + i, memZero + i + 1,
318
                sizeof(MemZero) * (nextIdx - i));
319
            /* Clear out top to make it easier to see what is to be checked. */
320
            XMEMSET(&memZero[nextIdx], 0, sizeof(MemZero));
321
        }
322
        /* Need to check this index again with new data. */
323
        i--;
324
    }
325
    wc_UnLockMutex(&zeroMutex);
326
}
327
#endif /* WOLFSSL_CHECK_MEM_ZERO */
328
329
#ifdef WOLFSSL_DEBUG_MEMORY
330
void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
331
#else
332
void* wolfSSL_Malloc(size_t size)
333
#endif
334
153k
{
335
153k
    void* res = 0;
336
337
#ifdef WOLFSSL_MEM_FAIL_COUNT
338
    if (!wc_MemFailCount_AllocMem()) {
339
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
340
        return NULL;
341
    }
342
#endif
343
344
#ifdef WOLFSSL_CHECK_MEM_ZERO
345
    /* Space for requested size. */
346
    size += MEM_ALIGN;
347
#endif
348
349
153k
    if (malloc_function) {
350
    #ifdef WOLFSSL_DEBUG_MEMORY
351
        res = malloc_function(size, func, line);
352
    #else
353
0
        res = malloc_function(size);
354
0
    #endif
355
0
    }
356
153k
    else {
357
153k
    #ifndef WOLFSSL_NO_MALLOC
358
        #ifdef WOLFSSL_TRAP_MALLOC_SZ
359
        if (size > WOLFSSL_TRAP_MALLOC_SZ) {
360
            WOLFSSL_MSG("Malloc too big!");
361
            return NULL;
362
        }
363
        #endif
364
365
153k
        res = malloc(size); /* native heap */
366
    #else
367
        WOLFSSL_MSG("No malloc available");
368
    #endif
369
153k
    }
370
371
#ifdef WOLFSSL_CHECK_MEM_ZERO
372
    /* Restore size to requested value. */
373
    size -= MEM_ALIGN;
374
    if (res != NULL) {
375
        /* Place size at front of allocated data and move pointer passed it. */
376
        *(size_t*)res = size;
377
        res = ((unsigned char*)res) + MEM_ALIGN;
378
    }
379
#endif
380
381
#ifdef WOLFSSL_DEBUG_MEMORY
382
#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
383
    fprintf(stderr, "Alloc: %p -> %u at %s:%u\n", res, (word32)size, func, line);
384
#else
385
    (void)func;
386
    (void)line;
387
#endif
388
#endif
389
390
#ifdef WOLFSSL_MALLOC_CHECK
391
    if (res == NULL)
392
        WOLFSSL_MSG("wolfSSL_malloc failed");
393
#endif
394
395
#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
396
    if (res && --gMemFailCount == 0) {
397
        fprintf(stderr, "\n---FORCED MEM FAIL TEST---\n");
398
        if (free_function) {
399
        #ifdef WOLFSSL_DEBUG_MEMORY
400
            free_function(res, func, line);
401
        #else
402
            free_function(res);
403
        #endif
404
        }
405
        else {
406
            free(res); /* native heap */
407
        }
408
        gMemFailCount = gMemFailCountSeed; /* reset */
409
        return NULL;
410
    }
411
#endif
412
413
153k
    return res;
414
153k
}
415
416
#ifdef WOLFSSL_DEBUG_MEMORY
417
void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
418
#else
419
void wolfSSL_Free(void *ptr)
420
#endif
421
153k
{
422
#ifdef WOLFSSL_DEBUG_MEMORY
423
#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
424
    fprintf(stderr, "Free: %p at %s:%u\n", ptr, func, line);
425
#else
426
    (void)func;
427
    (void)line;
428
#endif
429
#endif
430
431
#ifdef WOLFSSL_CHECK_MEM_ZERO
432
    /* Move pointer back to originally allocated pointer. */
433
    ptr = ((unsigned char*)ptr) - MEM_ALIGN;
434
    /* Check that the pointer is zero where required. */
435
    wc_MemZero_Check(((unsigned char*)ptr) + MEM_ALIGN, *(size_t*)ptr);
436
#endif
437
#ifdef WOLFSSL_MEM_FAIL_COUNT
438
    wc_MemFailCount_FreeMem();
439
#endif
440
441
153k
    if (free_function) {
442
    #ifdef WOLFSSL_DEBUG_MEMORY
443
        free_function(ptr, func, line);
444
    #else
445
0
        free_function(ptr);
446
0
    #endif
447
0
    }
448
153k
    else {
449
153k
    #ifndef WOLFSSL_NO_MALLOC
450
153k
        free(ptr); /* native heap */
451
    #else
452
        WOLFSSL_MSG("No free available");
453
    #endif
454
153k
    }
455
153k
}
456
457
#ifdef WOLFSSL_DEBUG_MEMORY
458
void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
459
#else
460
void* wolfSSL_Realloc(void *ptr, size_t size)
461
#endif
462
0
{
463
#ifdef WOLFSSL_CHECK_MEM_ZERO
464
    /* Can't check data that has been freed during realloc.
465
     * Manually allocated new memory, copy data and free original pointer.
466
     */
467
#ifdef WOLFSSL_DEBUG_MEMORY
468
    void* res = wolfSSL_Malloc(size, func, line);
469
#else
470
    void* res = wolfSSL_Malloc(size);
471
#endif
472
    if (ptr != NULL) {
473
        /* Copy the minimum of old and new size. */
474
        size_t copySize = *(size_t*)(((unsigned char*)ptr) - MEM_ALIGN);
475
        if (size < copySize) {
476
            copySize = size;
477
        }
478
        XMEMCPY(res, ptr, copySize);
479
        /* Dispose of old pointer. */
480
    #ifdef WOLFSSL_DEBUG_MEMORY
481
        wolfSSL_Free(ptr, func, line);
482
    #else
483
        wolfSSL_Free(ptr);
484
    #endif
485
    }
486
487
    /* Return new pointer with data copied into it. */
488
    return res;
489
#else
490
0
    void* res = 0;
491
492
#ifdef WOLFSSL_MEM_FAIL_COUNT
493
    if (!wc_MemFailCount_AllocMem()) {
494
        WOLFSSL_MSG("MemFailCnt: Fail realloc");
495
        return NULL;
496
    }
497
#endif
498
499
0
    if (realloc_function) {
500
    #ifdef WOLFSSL_DEBUG_MEMORY
501
        res = realloc_function(ptr, size, func, line);
502
    #else
503
0
        res = realloc_function(ptr, size);
504
0
    #endif
505
0
    }
506
0
    else {
507
0
    #ifndef WOLFSSL_NO_MALLOC
508
0
        res = realloc(ptr, size); /* native heap */
509
    #else
510
        WOLFSSL_MSG("No realloc available");
511
    #endif
512
0
    }
513
514
#ifdef WOLFSSL_MEM_FAIL_COUNT
515
    if (ptr != NULL) {
516
        wc_MemFailCount_FreeMem();
517
    }
518
#endif
519
520
0
    return res;
521
0
#endif
522
0
}
523
#endif /* WOLFSSL_STATIC_MEMORY */
524
525
#if defined(WOLFSSL_TRACK_MEMORY) && defined(USE_WOLFSSL_MEMORY) && \
526
    !defined(WOLFSSL_STATIC_MEMORY)
527
#include <wolfssl/wolfcrypt/mem_track.h>
528
WOLFSSL_API memoryStats *wc_MemStats_Ptr;
529
#endif /* WOLFSSL_TRACK_MEMORY && USE_WOLFSSL_MEMORY && !WOLFSSL_STATIC_MEMORY */
530
531
#ifdef WOLFSSL_STATIC_MEMORY
532
533
struct wc_Memory {
534
    byte*  buffer;
535
    struct wc_Memory* next;
536
#ifdef WOLFSSL_STATIC_MEMORY_LEAN
537
    /* lean static memory is assumed to be under 65k */
538
    word16 sz;
539
#else
540
    word32 sz;
541
#endif
542
#ifdef WOLFSSL_DEBUG_MEMORY
543
    word16 szUsed;
544
#endif
545
};
546
547
548
#ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK
549
static DebugMemoryCb DebugCb = NULL;
550
551
/* Used to set a debug memory callback. Helpful in cases where
552
 * printf is not available. */
553
void wolfSSL_SetDebugMemoryCb(DebugMemoryCb cb)
554
{
555
    DebugCb = cb;
556
}
557
#endif
558
559
/* returns amount of memory used on success. On error returns negative value
560
   wc_Memory** list is the list that new buckets are prepended to
561
 */
562
static int wc_create_memory_buckets(byte* buffer, word32 bufSz,
563
                              word32 buckSz, word32 buckNum, wc_Memory** list) {
564
    byte*  pt  = buffer;
565
    int    ret = 0;
566
    byte memSz   = (byte)sizeof(wc_Memory);
567
    word16 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
568
    word16 i;
569
570
    /* if not enough space available for bucket size then do not try */
571
    if (buckSz + memSz + padSz > bufSz) {
572
        return ret;
573
    }
574
575
    for (i = 0; i < buckNum; i++) {
576
        if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
577
            /* create a new struct and set its values */
578
            wc_Memory* mem = (struct wc_Memory*)(pt);
579
            mem->sz = buckSz;
580
            mem->buffer = (byte*)pt + padSz + memSz;
581
            mem->next = NULL;
582
583
        #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK
584
            if (DebugCb) {
585
                DebugCb(buckSz, buckSz, WOLFSSL_DEBUG_MEMORY_INIT, 0);
586
            }
587
        #endif
588
589
            /* add the newly created struct to front of list */
590
            if (*list == NULL) {
591
                *list = mem;
592
            } else {
593
                mem->next = *list;
594
                *list = mem;
595
            }
596
597
            /* advance pointer and keep track of memory used */
598
            ret += buckSz + padSz + memSz;
599
            pt  += buckSz + padSz + memSz;
600
        }
601
        else {
602
            break; /* not enough space left for more buckets of this size */
603
        }
604
    }
605
606
    return ret;
607
}
608
609
static int wc_partition_static_memory(byte* buffer, word32 sz, int flag,
610
                                                             WOLFSSL_HEAP* heap)
611
{
612
    word32 ava = sz;
613
    byte*  pt  = buffer;
614
    int    ret = 0;
615
    byte   memSz = (word32)sizeof(wc_Memory);
616
    byte   padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
617
618
    WOLFSSL_ENTER("wc_partition_static_memory");
619
620
    /* align pt */
621
    while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
622
        *pt = 0x00;
623
        pt++;
624
        ava--;
625
    }
626
627
#ifdef WOLFSSL_DEBUG_MEMORY
628
    fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt);
629
#endif
630
631
    /* divide into chunks of memory and add them to available list */
632
    while (ava >= (word32)(heap->sizeList[0] + padSz + memSz)) {
633
    #ifndef WOLFSSL_STATIC_MEMORY_LEAN
634
        /* creating only IO buffers from memory passed in, max TLS is 16k */
635
        if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
636
            if ((ret = wc_create_memory_buckets(pt, ava,
637
                            WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
638
                WOLFSSL_LEAVE("wc_partition_static_memory", ret);
639
                return ret;
640
            }
641
642
            /* check if no more room left for creating IO buffers */
643
            if (ret == 0) {
644
                break;
645
            }
646
647
            /* advance pointer in buffer for next buckets and keep track
648
               of how much memory is left available */
649
            pt  += ret;
650
            ava -= ret;
651
        }
652
        else
653
    #endif
654
        {
655
            int i;
656
            /* start at largest and move to smaller buckets */
657
            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
658
                if ((word32)(heap->sizeList[i] + padSz + memSz) <= ava) {
659
                    if ((ret = wc_create_memory_buckets(pt, ava,
660
                                    heap->sizeList[i], heap->distList[i],
661
                                    &(heap->ava[i]))) < 0) {
662
                        WOLFSSL_LEAVE("wc_partition_static_memory", ret);
663
                        return ret;
664
                    }
665
666
                    /* advance pointer in buffer for next buckets and keep track
667
                       of how much memory is left available */
668
                    pt  += ret;
669
                    ava -= ret;
670
                }
671
            }
672
        }
673
    }
674
675
    (void)flag;
676
    return 1;
677
}
678
679
static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz,
680
        const word32 *sizeList, const word32 *distList)
681
{
682
    unsigned int i;
683
684
    XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
685
686
    /* avoid XMEMCPY for LEAN static memory build */
687
    for (i = 0; i < listSz; i++) {
688
        heap->sizeList[i] = sizeList[i];
689
    }
690
691
    for (i = 0; i < listSz; i++) {
692
        heap->distList[i] = distList[i];
693
    }
694
695
#ifndef SINGLE_THREADED
696
    if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
697
        WOLFSSL_MSG("Error creating heap memory mutex");
698
        return BAD_MUTEX_E;
699
    }
700
#endif
701
702
    return 0;
703
}
704
705
int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint,
706
        unsigned int listSz, const word32 *sizeList,
707
        const word32 *distList, unsigned char *buf,
708
        unsigned int sz, int flag, int maxSz)
709
{
710
    WOLFSSL_HEAP*      heap = NULL;
711
    WOLFSSL_HEAP_HINT* hint = NULL;
712
    word16 idx = 0;
713
    int ret;
714
715
    WOLFSSL_ENTER("wc_LoadStaticMemory_ex");
716
717
    if (pHint == NULL || buf == NULL || sizeList == NULL || distList == NULL) {
718
        return BAD_FUNC_ARG;
719
    }
720
721
    /* Cap the listSz to the actual number of items allocated in the list. */
722
    if (listSz > WOLFMEM_MAX_BUCKETS) {
723
        WOLFSSL_MSG("Truncating the list of memory buckets");
724
        listSz = WOLFMEM_MAX_BUCKETS;
725
    }
726
727
    if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
728
        WOLFSSL_MSG("Not enough memory for partition tracking");
729
        return BUFFER_E; /* not enough memory for structures */
730
    }
731
732
    /* check if hint has already been assigned */
733
    if (*pHint == NULL) {
734
        heap = (WOLFSSL_HEAP*)buf;
735
        idx += sizeof(WOLFSSL_HEAP);
736
        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
737
        idx += sizeof(WOLFSSL_HEAP_HINT);
738
739
        ret = wc_init_memory_heap(heap, listSz, sizeList, distList);
740
        if (ret != 0) {
741
            return ret;
742
        }
743
744
        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
745
        hint->memory = heap;
746
    }
747
    else {
748
    #ifdef WOLFSSL_HEAP_TEST
749
        /* do not load in memory if test has been set */
750
        if (heap == (void*)WOLFSSL_HEAP_TEST) {
751
            return 0;
752
        }
753
    #endif
754
755
        hint = (WOLFSSL_HEAP_HINT*)(*pHint);
756
        heap = hint->memory;
757
    }
758
759
    ret = wc_partition_static_memory(buf + idx, sz - idx, flag, heap);
760
    if (ret != 1) {
761
        WOLFSSL_MSG("Error partitioning memory");
762
        return MEMORY_E;
763
    }
764
765
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
766
    /* determine what max applies too */
767
    if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
768
        heap->maxIO = maxSz;
769
    }
770
    else { /* general memory used in handshakes */
771
        heap->maxHa = maxSz;
772
    }
773
    heap->flag |= flag;
774
#endif
775
    *pHint = hint;
776
777
    (void)maxSz;
778
    return 0;
779
}
780
781
int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
782
    unsigned char* buf, unsigned int sz, int flag, int maxSz)
783
{
784
    word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
785
    word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST };
786
    int ret = 0;
787
788
    WOLFSSL_ENTER("wc_LoadStaticMemory");
789
    ret = wc_LoadStaticMemory_ex(pHint,
790
            WOLFMEM_DEF_BUCKETS, sizeList, distList,
791
            buf, sz, flag, maxSz);
792
    WOLFSSL_LEAVE("wc_LoadStaticMemory", ret);
793
    return ret;
794
}
795
796
797
void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap)
798
{
799
    WOLFSSL_ENTER("wc_UnloadStaticMemory");
800
#ifndef SINGLE_THREADED
801
    if (heap != NULL && heap->memory != NULL) {
802
        wc_FreeMutex(&heap->memory->memory_mutex);
803
    }
804
#else
805
    (void)heap;
806
#endif
807
}
808
809
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
810
/* returns the size of management memory needed for each bucket.
811
 * This is memory that is used to keep track of and align memory buckets. */
812
int wolfSSL_MemoryPaddingSz(void)
813
{
814
    word32 memSz = (word32)sizeof(wc_Memory);
815
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
816
    return memSz + padSz;
817
}
818
819
820
/* Used to calculate memory size for optimum use with buckets.
821
   returns the suggested size rounded down to the nearest bucket. */
822
int wolfSSL_StaticBufferSz_ex(unsigned int listSz,
823
        const word32 *sizeList, const word32 *distList,
824
        byte* buffer, word32 sz, int flag)
825
{
826
    word32 ava = sz;
827
    byte*  pt  = buffer;
828
    word32 memSz = (word32)sizeof(wc_Memory);
829
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
830
831
    WOLFSSL_ENTER("wolfSSL_StaticBufferSz_ex");
832
833
    if (buffer == NULL || sizeList == NULL || distList == NULL) {
834
        return BAD_FUNC_ARG;
835
    }
836
837
    /* Cap the listSz to the actual number of items allocated in the list. */
838
    if (listSz > WOLFMEM_MAX_BUCKETS) {
839
        WOLFSSL_MSG("Truncating the list of memory buckets");
840
        listSz = WOLFMEM_MAX_BUCKETS;
841
    }
842
843
    /* align pt */
844
    while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
845
        pt++;
846
        ava--;
847
    }
848
849
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
850
    /* creating only IO buffers from memory passed in, max TLS is 16k */
851
    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
852
        if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
853
            return 0; /* not enough room for even one bucket */
854
        }
855
856
        ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
857
    }
858
    else
859
#endif
860
    {
861
        int i, k;
862
863
        if (ava < (sizeList[0] + padSz + memSz)) {
864
            return 0; /* not enough room for even one bucket */
865
        }
866
867
        while ((ava >= (sizeList[0] + padSz + memSz)) && (ava > 0)) {
868
            /* start at largest and move to smaller buckets */
869
            for (i = (listSz - 1); i >= 0; i--) {
870
                for (k = distList[i]; k > 0; k--) {
871
                    if ((sizeList[i] + padSz + memSz) <= ava) {
872
                        ava -= sizeList[i] + padSz + memSz;
873
                    }
874
                }
875
            }
876
        }
877
    }
878
879
    WOLFSSL_LEAVE("wolfSSL_StaticBufferSz_ex", sz - ava);
880
    return sz - ava; /* round down */
881
}
882
883
884
/* Calls wolfSSL_StaticBufferSz_ex with the static memory pool config
885
 * used by wolfSSL by default. */
886
int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
887
{
888
    word32 bucketSz[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_BUCKETS};
889
    word32 distList[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_DIST};
890
891
    return wolfSSL_StaticBufferSz_ex(WOLFMEM_DEF_BUCKETS, bucketSz, distList,
892
        buffer, sz, flag);
893
}
894
895
896
int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
897
{
898
    WOLFSSL_MSG("Freeing fixed IO buffer");
899
900
    /* check if fixed buffer was set */
901
    if (*io == NULL) {
902
        return 1;
903
    }
904
905
    if (heap == NULL) {
906
        WOLFSSL_MSG("No heap to return fixed IO too");
907
    }
908
    else {
909
        /* put IO buffer back into IO pool */
910
        (*io)->next = heap->io;
911
        heap->io    = *io;
912
        *io         = NULL;
913
    }
914
915
    return 1;
916
}
917
918
919
int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
920
{
921
    WOLFSSL_MSG("Setting fixed IO for SSL");
922
    if (heap == NULL) {
923
        return MEMORY_E;
924
    }
925
926
    *io = heap->io;
927
928
    if (*io != NULL) {
929
        heap->io = (*io)->next;
930
        (*io)->next = NULL;
931
    }
932
    else { /* failed to grab an IO buffer */
933
        return 0;
934
    }
935
936
    return 1;
937
}
938
939
940
int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
941
{
942
        word32     i;
943
        wc_Memory* pt;
944
945
        XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
946
947
        stats->totalAlloc = heap->alloc;
948
        stats->totalFr    = heap->frAlc;
949
        stats->curAlloc   = stats->totalAlloc - stats->totalFr;
950
        stats->maxHa      = heap->maxHa;
951
        stats->maxIO      = heap->maxIO;
952
        for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
953
            stats->blockSz[i] = heap->sizeList[i];
954
            for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
955
                stats->avaBlock[i] += 1;
956
            }
957
        }
958
959
        for (pt = heap->io; pt != NULL; pt = pt->next) {
960
            stats->avaIO++;
961
        }
962
963
        stats->flag       = heap->flag; /* flag used */
964
965
    return 1;
966
}
967
#endif /* !WOLFSSL_STATIC_MEMORY_LEAN */
968
969
970
/* global heap hint to fall back on when no heap hint is passed to
971
 * XMALLOC/XFREE
972
 * NOT thread safe, should be set once before any expected XMALLOC XFREE calls
973
 */
974
static void* globalHeapHint = NULL;
975
976
977
/* Used to set a new global heap hint. Returns a pointer to the current global
978
 * heap hint before being set. */
979
void* wolfSSL_SetGlobalHeapHint(void* heap)
980
{
981
    void *oldHint = globalHeapHint;
982
983
    globalHeapHint = heap;
984
    return oldHint;
985
}
986
987
988
/* returns a pointer to the current global heap hint */
989
void* wolfSSL_GetGlobalHeapHint(void)
990
{
991
    return globalHeapHint;
992
}
993
994
995
#ifdef WOLFSSL_DEBUG_MEMORY
996
void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
997
#else
998
void* wolfSSL_Malloc(size_t size, void* heap, int type)
999
#endif
1000
{
1001
    void* res = 0;
1002
    wc_Memory* pt = NULL;
1003
    int   i;
1004
1005
    /* check for testing heap hint was set */
1006
#ifdef WOLFSSL_HEAP_TEST
1007
    if (heap == (void*)WOLFSSL_HEAP_TEST) {
1008
        return malloc(size); /* native heap */
1009
    }
1010
#endif
1011
1012
    /* if no heap hint then use dynamic memory*/
1013
    if (heap == NULL && globalHeapHint == NULL) {
1014
        #ifdef WOLFSSL_HEAP_TEST
1015
            /* allow using malloc for creating ctx and method */
1016
            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
1017
                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
1018
                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method");
1019
                res = malloc(size); /* native heap */
1020
            }
1021
            else {
1022
                WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC");
1023
                res = NULL;
1024
            }
1025
        #else
1026
        #ifndef WOLFSSL_NO_MALLOC
1027
            #ifdef FREERTOS
1028
                res = pvPortMalloc(size); /* native heap */
1029
            #elif defined(WOLFSSL_EMBOS)
1030
                res = OS_HEAP_malloc(size);
1031
            #else
1032
                res = malloc(size); /* native heap */
1033
            #endif
1034
1035
            #ifdef WOLFSSL_DEBUG_MEMORY
1036
                fprintf(stderr, "[HEAP %p] Alloc: %p -> %u at %s:%u\n", heap,
1037
                    res, (word32)size, func, line);
1038
            #endif
1039
        #else
1040
            WOLFSSL_MSG("No heap hint found to use and no malloc");
1041
            #ifdef WOLFSSL_DEBUG_MEMORY
1042
            fprintf(stderr, "ERROR: at %s:%u\n", func, line);
1043
            #endif
1044
        #endif /* WOLFSSL_NO_MALLOC */
1045
        #endif /* WOLFSSL_HEAP_TEST */
1046
    }
1047
    else {
1048
        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
1049
        WOLFSSL_HEAP*      mem;
1050
1051
        if (hint == NULL) {
1052
            hint = (WOLFSSL_HEAP_HINT*)globalHeapHint;
1053
        #ifdef WOLFSSL_DEBUG_MEMORY
1054
            fprintf(stderr, "(Using global heap hint %p) ", hint);
1055
        #endif
1056
        }
1057
        mem = hint->memory;
1058
1059
    #ifndef SINGLE_THREADED
1060
        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1061
            WOLFSSL_MSG("Bad memory_mutex lock");
1062
            return NULL;
1063
        }
1064
    #endif
1065
1066
    #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1067
        /* case of using fixed IO buffers */
1068
        if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
1069
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1070
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1071
            if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1072
                pt = hint->outBuf;
1073
            }
1074
            if (type == DYNAMIC_TYPE_IN_BUFFER) {
1075
                pt = hint->inBuf;
1076
            }
1077
        }
1078
        else
1079
    #endif
1080
        {
1081
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1082
            /* check if using IO pool flag */
1083
            if (mem->flag & WOLFMEM_IO_POOL &&
1084
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1085
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1086
                if (mem->io != NULL) {
1087
                    pt      = mem->io;
1088
                    mem->io = pt->next;
1089
                }
1090
            }
1091
         #endif
1092
1093
            /* general static memory */
1094
            if (pt == NULL) {
1095
                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
1096
                    if ((word32)size <= mem->sizeList[i]) {
1097
                        if (mem->ava[i] != NULL) {
1098
                            pt = mem->ava[i];
1099
                            mem->ava[i] = pt->next;
1100
                            break;
1101
                        }
1102
                    #ifdef WOLFSSL_DEBUG_STATIC_MEMORY
1103
                        else {
1104
                            fprintf(stderr, "Size: %lu, Empty: %d\n",
1105
                                (unsigned long) size, mem->sizeList[i]);
1106
                        }
1107
                    #endif
1108
                    }
1109
                }
1110
            }
1111
        }
1112
1113
        if (pt != NULL) {
1114
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1115
            mem->alloc += 1;
1116
        #endif
1117
            res = pt->buffer;
1118
1119
        #ifdef WOLFSSL_DEBUG_MEMORY
1120
            pt->szUsed = size;
1121
            fprintf(stderr, "[HEAP %p] Alloc: %p -> %lu at %s:%u\n", heap,
1122
                pt->buffer, size, func, line);
1123
        #endif
1124
        #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK
1125
            if (DebugCb) {
1126
                DebugCb(size, pt->sz, WOLFSSL_DEBUG_MEMORY_ALLOC, type);
1127
            }
1128
        #endif
1129
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1130
            /* keep track of connection statistics if flag is set */
1131
            if (mem->flag & WOLFMEM_TRACK_STATS) {
1132
                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
1133
                if (stats != NULL) {
1134
                    stats->curMem += pt->sz;
1135
                    if (stats->peakMem < stats->curMem) {
1136
                        stats->peakMem = stats->curMem;
1137
                    }
1138
                    stats->curAlloc++;
1139
                    if (stats->peakAlloc < stats->curAlloc) {
1140
                        stats->peakAlloc = stats->curAlloc;
1141
                    }
1142
                    stats->totalAlloc++;
1143
                }
1144
            }
1145
        #endif
1146
        }
1147
        else {
1148
            WOLFSSL_MSG("ERROR ran out of static memory");
1149
            res = NULL;
1150
            #ifdef WOLFSSL_DEBUG_MEMORY
1151
                fprintf(stderr, "Looking for %lu bytes at %s:%u\n",
1152
                    (unsigned long) size, func, line);
1153
            #endif
1154
            #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK
1155
            if (DebugCb) {
1156
                DebugCb(size, 0, WOLFSSL_DEBUG_MEMORY_FAIL, type);
1157
            }
1158
            #endif
1159
        }
1160
    #ifndef SINGLE_THREADED
1161
        wc_UnLockMutex(&(mem->memory_mutex));
1162
    #endif
1163
    }
1164
1165
    #ifdef WOLFSSL_MALLOC_CHECK
1166
        if ((wc_ptr_t)res % WOLFSSL_STATIC_ALIGN) {
1167
            WOLFSSL_MSG("ERROR memory is not aligned");
1168
            res = NULL;
1169
        }
1170
    #endif
1171
1172
1173
    (void)i;
1174
    (void)pt;
1175
    (void)type;
1176
1177
    return res;
1178
}
1179
1180
1181
#ifdef WOLFSSL_DEBUG_MEMORY
1182
void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
1183
#else
1184
void wolfSSL_Free(void *ptr, void* heap, int type)
1185
#endif
1186
{
1187
    int i;
1188
1189
    if (ptr) {
1190
        /* check for testing heap hint was set */
1191
    #ifdef WOLFSSL_HEAP_TEST
1192
        if (heap == (void*)WOLFSSL_HEAP_TEST) {
1193
        #ifdef WOLFSSL_DEBUG_MEMORY
1194
            fprintf(stderr, "[HEAP %p] Free: %p at %s:%u\n", heap, ptr, func,
1195
                line);
1196
        #endif
1197
            return free(ptr); /* native heap */
1198
        }
1199
    #endif
1200
1201
        if (heap == NULL && globalHeapHint == NULL) {
1202
        #ifdef WOLFSSL_HEAP_TEST
1203
            /* allow using malloc for creating ctx and method */
1204
            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
1205
                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
1206
                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method");
1207
            }
1208
            else {
1209
                WOLFSSL_MSG("ERROR null heap hint passed into XFREE");
1210
            }
1211
        #endif
1212
        #ifndef WOLFSSL_NO_MALLOC
1213
            #ifdef WOLFSSL_DEBUG_MEMORY
1214
            fprintf(stderr, "[HEAP %p] Free: %p at %s:%u\n", heap, ptr, func,
1215
                line);
1216
            #endif
1217
            #ifdef FREERTOS
1218
                vPortFree(ptr); /* native heap */
1219
            #elif defined(WOLFSSL_EMBOS)
1220
                OS_HEAP_free(ptr); /* native heap */
1221
            #else
1222
                free(ptr); /* native heap */
1223
            #endif
1224
        #else
1225
            WOLFSSL_MSG("Error trying to call free when turned off");
1226
        #endif /* WOLFSSL_NO_MALLOC */
1227
        }
1228
        else {
1229
            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
1230
            WOLFSSL_HEAP*      mem;
1231
            wc_Memory* pt;
1232
            word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
1233
1234
            if (hint == NULL) {
1235
                hint = (WOLFSSL_HEAP_HINT*)globalHeapHint;
1236
            #ifdef WOLFSSL_DEBUG_MEMORY
1237
                fprintf(stderr, "(Using global heap hint %p) ", hint);
1238
            #endif
1239
            }
1240
            mem = hint->memory;
1241
            if (mem == NULL) {
1242
                WOLFSSL_MSG("Bad hint pointer to memory");
1243
                return;
1244
            }
1245
1246
            /* get memory struct and add it to available list */
1247
            pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
1248
        #ifndef SINGLE_THREADED
1249
            if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1250
                WOLFSSL_MSG("Bad memory_mutex lock");
1251
                return;
1252
            }
1253
        #endif
1254
1255
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1256
            /* case of using fixed IO buffers */
1257
            if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
1258
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1259
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1260
                /* fixed IO pools are free'd at the end of SSL lifetime
1261
                   using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
1262
            }
1263
            else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
1264
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1265
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1266
                pt->next = mem->io;
1267
                mem->io  = pt;
1268
            }
1269
            else
1270
       #endif
1271
            { /* general memory free */
1272
                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
1273
                    if (pt->sz == mem->sizeList[i]) {
1274
                        pt->next = mem->ava[i];
1275
                        mem->ava[i] = pt;
1276
1277
                    #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK
1278
                        if (DebugCb) {
1279
                        #ifdef WOLFSSL_DEBUG_MEMORY
1280
                            DebugCb(pt->szUsed, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type);
1281
                        #else
1282
                            DebugCb(pt->sz, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type);
1283
                        #endif
1284
                        }
1285
                    #endif
1286
                        break;
1287
                    }
1288
                }
1289
            }
1290
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1291
            mem->inUse -= pt->sz;
1292
            mem->frAlc += 1;
1293
        #endif
1294
1295
        #ifdef WOLFSSL_DEBUG_MEMORY
1296
            fprintf(stderr, "[HEAP %p] Free: %p -> %u at %s:%u\n", heap,
1297
                pt->buffer, pt->szUsed, func, line);
1298
        #endif
1299
1300
        #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1301
            /* keep track of connection statistics if flag is set */
1302
            if (mem->flag & WOLFMEM_TRACK_STATS) {
1303
                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
1304
                if (stats != NULL) {
1305
                    /* avoid under flow */
1306
                    if (stats->curMem > pt->sz) {
1307
                        stats->curMem -= pt->sz;
1308
                    }
1309
                    else {
1310
                        stats->curMem = 0;
1311
                    }
1312
1313
                    if (stats->curAlloc > 0) {
1314
                        stats->curAlloc--;
1315
                    }
1316
                    stats->totalFr++;
1317
                }
1318
            }
1319
        #endif
1320
        #ifndef SINGLE_THREADED
1321
            wc_UnLockMutex(&(mem->memory_mutex));
1322
        #endif
1323
        }
1324
    }
1325
1326
    (void)i;
1327
    (void)type;
1328
}
1329
1330
#ifndef WOLFSSL_NO_REALLOC
1331
#ifdef WOLFSSL_DEBUG_MEMORY
1332
void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
1333
#else
1334
void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
1335
#endif
1336
{
1337
    void* res = 0;
1338
    wc_Memory* pt = NULL;
1339
    int    i;
1340
1341
    /* check for testing heap hint was set */
1342
#ifdef WOLFSSL_HEAP_TEST
1343
    if (heap == (void*)WOLFSSL_HEAP_TEST) {
1344
        return realloc(ptr, size); /* native heap */
1345
    }
1346
#endif
1347
1348
    if (heap == NULL && globalHeapHint == NULL) {
1349
        #ifdef WOLFSSL_HEAP_TEST
1350
            WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC");
1351
        #endif
1352
        #ifndef WOLFSSL_NO_MALLOC
1353
            res = realloc(ptr, size); /* native heap */
1354
        #else
1355
            WOLFSSL_MSG("NO heap found to use for realloc");
1356
        #endif /* WOLFSSL_NO_MALLOC */
1357
    }
1358
    else {
1359
        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
1360
        WOLFSSL_HEAP*      mem;
1361
        word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
1362
1363
        if (hint == NULL) {
1364
            hint = (WOLFSSL_HEAP_HINT*)globalHeapHint;
1365
        #ifdef WOLFSSL_DEBUG_MEMORY
1366
            fprintf(stderr, "(Using global heap hint %p) ", hint);
1367
        #endif
1368
        }
1369
        mem = hint->memory;
1370
1371
        if (ptr == NULL) {
1372
        #ifdef WOLFSSL_DEBUG_MEMORY
1373
            return wolfSSL_Malloc(size, heap, type, func, line);
1374
        #else
1375
            return wolfSSL_Malloc(size, heap, type);
1376
        #endif
1377
        }
1378
    #ifndef SINGLE_THREADED
1379
        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1380
            WOLFSSL_MSG("Bad memory_mutex lock");
1381
            return NULL;
1382
        }
1383
    #endif
1384
1385
    #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1386
        /* case of using fixed IO buffers or IO pool */
1387
        if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
1388
                                          && (type == DYNAMIC_TYPE_OUT_BUFFER ||
1389
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1390
            /* no realloc, is fixed size */
1391
            pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
1392
            if (pt->sz < size) {
1393
                WOLFSSL_MSG("Error IO memory was not large enough");
1394
                res = NULL; /* return NULL in error case */
1395
            }
1396
            else {
1397
                res = pt->buffer;
1398
            }
1399
        }
1400
        else
1401
    #endif
1402
        {
1403
        /* general memory */
1404
            for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
1405
                if ((word32)size <= mem->sizeList[i]) {
1406
                    if (mem->ava[i] != NULL) {
1407
                        pt = mem->ava[i];
1408
                        mem->ava[i] = pt->next;
1409
                        break;
1410
                    }
1411
                }
1412
            }
1413
1414
            if (pt != NULL) {
1415
                word32 prvSz;
1416
1417
                res = pt->buffer;
1418
1419
                /* copy over original information and free ptr */
1420
                prvSz = ((wc_Memory*)((byte*)ptr - padSz -
1421
                                               sizeof(wc_Memory)))->sz;
1422
                prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
1423
                XMEMCPY(pt->buffer, ptr, prvSz);
1424
            #ifndef WOLFSSL_STATIC_MEMORY_LEAN
1425
                mem->inUse += pt->sz;
1426
                mem->alloc += 1;
1427
            #endif
1428
1429
                /* free memory that was previously being used */
1430
            #ifndef SINGLE_THREADED
1431
                wc_UnLockMutex(&(mem->memory_mutex));
1432
            #endif
1433
                wolfSSL_Free(ptr, heap, type
1434
            #ifdef WOLFSSL_DEBUG_MEMORY
1435
                    , func, line
1436
            #endif
1437
                );
1438
            #ifndef SINGLE_THREADED
1439
                if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1440
                    WOLFSSL_MSG("Bad memory_mutex lock");
1441
                    return NULL;
1442
                }
1443
            #endif
1444
            }
1445
        }
1446
    #ifndef SINGLE_THREADED
1447
        wc_UnLockMutex(&(mem->memory_mutex));
1448
    #endif
1449
    }
1450
1451
    #ifdef WOLFSSL_MALLOC_CHECK
1452
        if ((wc_ptr_t)res % WOLFSSL_STATIC_ALIGN) {
1453
            WOLFSSL_MSG("ERROR memory is not aligned");
1454
            res = NULL;
1455
        }
1456
    #endif
1457
1458
    (void)i;
1459
    (void)pt;
1460
    (void)type;
1461
1462
    return res;
1463
}
1464
#endif /* WOLFSSL_STATIC_MEMORY */
1465
#endif /* WOLFSSL_NO_REALLOC */
1466
#endif /* USE_WOLFSSL_MEMORY */
1467
1468
1469
#ifdef HAVE_IO_POOL
1470
1471
/* Example for user io pool, shared build may need definitions in lib proper */
1472
1473
#include <stdlib.h>
1474
1475
#ifndef HAVE_THREAD_LS
1476
    #error "Oops, simple I/O pool example needs thread local storage"
1477
#endif
1478
1479
1480
/* allow simple per thread in and out pools */
1481
/* use 17k size since max record size is 16k plus overhead */
1482
static THREAD_LS_T byte pool_in[17*1024];
1483
static THREAD_LS_T byte pool_out[17*1024];
1484
1485
1486
void* XMALLOC(size_t n, void* heap, int type)
1487
{
1488
    (void)heap;
1489
1490
    if (type == DYNAMIC_TYPE_IN_BUFFER) {
1491
        if (n < sizeof(pool_in))
1492
            return pool_in;
1493
        else
1494
            return NULL;
1495
    }
1496
1497
    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1498
        if (n < sizeof(pool_out))
1499
            return pool_out;
1500
        else
1501
            return NULL;
1502
    }
1503
1504
    return malloc(n); /* native heap */
1505
}
1506
1507
void* XREALLOC(void *p, size_t n, void* heap, int type)
1508
{
1509
    (void)heap;
1510
1511
    if (type == DYNAMIC_TYPE_IN_BUFFER) {
1512
        if (n < sizeof(pool_in))
1513
            return pool_in;
1514
        else
1515
            return NULL;
1516
    }
1517
1518
    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1519
        if (n < sizeof(pool_out))
1520
            return pool_out;
1521
        else
1522
            return NULL;
1523
    }
1524
1525
    return realloc(p, n); /* native heap */
1526
}
1527
1528
void XFREE(void *p, void* heap, int type)
1529
{
1530
    (void)heap;
1531
1532
    if (type == DYNAMIC_TYPE_IN_BUFFER)
1533
        return;  /* do nothing, static pool */
1534
1535
    if (type == DYNAMIC_TYPE_OUT_BUFFER)
1536
        return;  /* do nothing, static pool */
1537
1538
    free(p); /* native heap */
1539
}
1540
1541
#endif /* HAVE_IO_POOL */
1542
1543
#ifdef WOLFSSL_MEMORY_LOG
1544
void *xmalloc(size_t n, void* heap, int type, const char* func,
1545
              const char* file, unsigned int line)
1546
{
1547
    void*   p = NULL;
1548
    word32* p32;
1549
1550
#ifdef WOLFSSL_MEM_FAIL_COUNT
1551
    if (!wc_MemFailCount_AllocMem()) {
1552
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
1553
        return NULL;
1554
    }
1555
#endif
1556
1557
    if (malloc_function) {
1558
#if !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
1559
        p32 = malloc_function(n + sizeof(word32) * 4);
1560
#else
1561
        p32 = malloc_function(n + sizeof(word32) * 4, heap, type);
1562
#endif
1563
    }
1564
    else
1565
        p32 = malloc(n + sizeof(word32) * 4); /* native heap */
1566
1567
    if (p32 != NULL) {
1568
        p32[0] = (word32)n;
1569
        p = (void*)(p32 + 4);
1570
1571
        fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n,
1572
                                                        type, func, file, line);
1573
    }
1574
1575
    (void)heap;
1576
1577
    return p;
1578
}
1579
void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
1580
               const char* file, unsigned int line)
1581
{
1582
    void*   newp = NULL;
1583
    word32* p32;
1584
    word32* oldp32 = NULL;
1585
    word32  oldLen;
1586
1587
#ifdef WOLFSSL_MEM_FAIL_COUNT
1588
    if (!wc_MemFailCount_AllocMem()) {
1589
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
1590
        return NULL;
1591
    }
1592
#endif
1593
1594
    if (p != NULL) {
1595
        oldp32 = (word32*)p;
1596
        oldp32 -= 4;
1597
        oldLen = oldp32[0];
1598
    }
1599
1600
    if (realloc_function) {
1601
#if !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
1602
        p32 = realloc_function(oldp32, n + sizeof(word32) * 4);
1603
#else
1604
        p32 = realloc_function(oldp32, n + sizeof(word32) * 4, heap, type);
1605
#endif
1606
    }
1607
    else
1608
        p32 = realloc(oldp32, n + sizeof(word32) * 4); /* native heap */
1609
1610
    if (p32 != NULL) {
1611
        p32[0] = (word32)n;
1612
        newp = (void*)(p32 + 4);
1613
1614
        if (p != NULL) {
1615
            fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen,
1616
                                                        type, func, file, line);
1617
        }
1618
        fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n,
1619
                                                        type, func, file, line);
1620
    }
1621
1622
#ifdef WOLFSSL_MEM_FAIL_COUNT
1623
    if (p != NULL) {
1624
        wc_MemFailCount_FreeMem();
1625
    }
1626
#endif
1627
1628
    (void)heap;
1629
1630
    return newp;
1631
}
1632
void xfree(void *p, void* heap, int type, const char* func, const char* file,
1633
           unsigned int line)
1634
{
1635
    word32* p32 = (word32*)p;
1636
1637
    if (p != NULL) {
1638
    #ifdef WOLFSSL_MEM_FAIL_COUNT
1639
        wc_MemFailCount_FreeMem();
1640
    #endif
1641
        p32 -= 4;
1642
1643
        fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,
1644
                                                              func, file, line);
1645
1646
        if (free_function) {
1647
#if !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
1648
            free_function(p32);
1649
#else
1650
            free_function(p32, heap, type);
1651
#endif
1652
        }
1653
        else
1654
            free(p32); /* native heap */
1655
    }
1656
1657
    (void)heap;
1658
}
1659
#endif /* WOLFSSL_MEMORY_LOG */
1660
1661
#ifdef WOLFSSL_STACK_LOG
1662
/* Note: this code only works with GCC using -finstrument-functions. */
1663
void __attribute__((no_instrument_function))
1664
     __cyg_profile_func_enter(void *func,  void *caller)
1665
{
1666
    register void* sp asm("sp");
1667
    fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(wc_ptr_t)func, sp);
1668
    (void)caller;
1669
}
1670
1671
void __attribute__((no_instrument_function))
1672
     __cyg_profile_func_exit(void *func, void *caller)
1673
{
1674
    register void* sp asm("sp");
1675
    fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(wc_ptr_t)func, sp);
1676
    (void)caller;
1677
}
1678
#endif
1679
1680
#ifndef WOLFSSL_NO_FORCE_ZERO
1681
/* Exported version of ForceZero(). */
1682
void wc_ForceZero(void *mem, size_t len)
1683
310k
{
1684
310k
    ForceZero(mem, len);
1685
310k
}
1686
#endif
1687
1688
#ifndef WOLFSSL_NO_CONST_CMP
1689
/* Exported version of ConstantCompare(). */
1690
int wc_ConstantCompare(const byte* a, const byte* b, int length)
1691
1692
0
{
1693
0
    return ConstantCompare(a, b, length);
1694
0
}
1695
#endif
1696
1697
#ifdef WC_DEBUG_CIPHER_LIFECYCLE
1698
static const byte wc_debug_cipher_lifecycle_tag_value[] =
1699
    { 'W', 'o', 'l', 'f' };
1700
1701
WOLFSSL_LOCAL int wc_debug_CipherLifecycleInit(
1702
    void **CipherLifecycleTag,
1703
    void *heap)
1704
{
1705
    if (CipherLifecycleTag == NULL)
1706
        return BAD_FUNC_ARG;
1707
    *CipherLifecycleTag = (void *)XMALLOC(
1708
        sizeof(wc_debug_cipher_lifecycle_tag_value),
1709
        heap,
1710
        DYNAMIC_TYPE_DEBUG_TAG);
1711
    if (*CipherLifecycleTag == NULL)
1712
        return MEMORY_E;
1713
    XMEMCPY(*CipherLifecycleTag,
1714
            wc_debug_cipher_lifecycle_tag_value,
1715
            sizeof(wc_debug_cipher_lifecycle_tag_value));
1716
    return 0;
1717
}
1718
1719
WOLFSSL_LOCAL int wc_debug_CipherLifecycleCheck(
1720
    void *CipherLifecycleTag,
1721
    int abort_p)
1722
{
1723
    int ret;
1724
    if (CipherLifecycleTag == NULL) {
1725
        ret = BAD_STATE_E;
1726
        goto out;
1727
    }
1728
    if (XMEMCMP(CipherLifecycleTag,
1729
                wc_debug_cipher_lifecycle_tag_value,
1730
                sizeof(wc_debug_cipher_lifecycle_tag_value)) != 0)
1731
    {
1732
        ret = BAD_STATE_E;
1733
        goto out;
1734
    }
1735
    ret = 0;
1736
1737
out:
1738
#ifdef WOLFSSL_KERNEL_MODE
1739
    (void)abort_p;
1740
#else
1741
    if ((ret < 0) && abort_p)
1742
        abort();
1743
#endif
1744
1745
    return ret;
1746
}
1747
1748
WOLFSSL_LOCAL int wc_debug_CipherLifecycleFree(
1749
    void **CipherLifecycleTag,
1750
    void *heap,
1751
    int abort_p)
1752
{
1753
    int ret;
1754
    if (CipherLifecycleTag == NULL)
1755
        return BAD_FUNC_ARG;
1756
    ret = wc_debug_CipherLifecycleCheck(*CipherLifecycleTag, abort_p);
1757
    if (ret != 0)
1758
        return ret;
1759
    XFREE(*CipherLifecycleTag, heap, DYNAMIC_TYPE_DEBUG_TAG);
1760
    *CipherLifecycleTag = NULL;
1761
    return 0;
1762
}
1763
#endif /* WC_DEBUG_CIPHER_LIFECYCLE */
1764
1765
#ifdef DEBUG_VECTOR_REGISTER_ACCESS
1766
THREAD_LS_T int wc_svr_count = 0;
1767
THREAD_LS_T const char *wc_svr_last_file = NULL;
1768
THREAD_LS_T int wc_svr_last_line = -1;
1769
THREAD_LS_T int wc_debug_vector_registers_retval =
1770
    WC_DEBUG_VECTOR_REGISTERS_RETVAL_INITVAL;
1771
#endif
1772
1773
#ifdef DEBUG_VECTOR_REGISTER_ACCESS_FUZZING
1774
1775
#ifdef HAVE_THREAD_LS
1776
1777
WOLFSSL_LOCAL int SAVE_VECTOR_REGISTERS2_fuzzer(void) {
1778
    static THREAD_LS_T struct drand48_data wc_svr_fuzzing_state;
1779
    static THREAD_LS_T int wc_svr_fuzzing_seeded = 0;
1780
    long result;
1781
1782
#ifdef DEBUG_VECTOR_REGISTER_ACCESS
1783
    if (wc_debug_vector_registers_retval)
1784
        return wc_debug_vector_registers_retval;
1785
#endif
1786
1787
    if (wc_svr_fuzzing_seeded == 0) {
1788
        long seed = WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED;
1789
        char *seed_envstr = getenv("WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED");
1790
        if (seed_envstr)
1791
            seed = strtol(seed_envstr, NULL, 0);
1792
        (void)srand48_r(seed, &wc_svr_fuzzing_state);
1793
        wc_svr_fuzzing_seeded = 1;
1794
    }
1795
    (void)lrand48_r(&wc_svr_fuzzing_state, &result);
1796
    if (result & 1)
1797
        return WC_NO_ERR_TRACE(IO_FAILED_E);
1798
    else
1799
        return 0;
1800
}
1801
1802
#else /* !HAVE_THREAD_LS */
1803
1804
/* alternate implementation useful for testing in the kernel module build, where
1805
 * glibc and thread-local storage are unavailable.
1806
 */
1807
1808
WOLFSSL_LOCAL int SAVE_VECTOR_REGISTERS2_fuzzer(void) {
1809
    /* xorshift64 (Marsaglia 2003): a bijection on the nonzero 64-bit states
1810
     * with a single cycle of period 2^64 - 1 -- no state-space contraction,
1811
     * no short cycles, and the seed selects only the phase.  Aligned 64-bit
1812
     * stores are atomic on supported targets and every stored value is
1813
     * nonzero, so unsynchronized concurrent access loses updates but can
1814
     * never degenerate the state.
1815
     */
1816
    static word64 prn =
1817
        (word64)WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED != W64LIT(0) ?
1818
        (word64)WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED :
1819
        W64LIT(0x9e3779b97f4a7c15); /* zero is the map's one fixed point --
1820
                                     * substitute an arbitrary nonzero seed.
1821
                                     */
1822
    word64 x;
1823
1824
#ifdef DEBUG_VECTOR_REGISTER_ACCESS
1825
    if (wc_debug_vector_registers_retval)
1826
        return wc_debug_vector_registers_retval;
1827
#endif
1828
1829
    x = prn;
1830
    x ^= x << 13;
1831
    x ^= x >> 7;
1832
    x ^= x << 17;
1833
    prn = x;
1834
1835
    return ((x >> 32) & 1) ? WC_NO_ERR_TRACE(IO_FAILED_E) : 0;
1836
}
1837
1838
#endif /* !HAVE_THREAD_LS */
1839
1840
#endif /* DEBUG_VECTOR_REGISTER_ACCESS_FUZZING */
1841
1842
#if defined(WOLFSSL_LINUXKM) || defined(WC_SYM_RELOC_TABLES) || \
1843
    defined(WC_SYM_RELOC_TABLES_SUPPORT)
1844
    #include "linuxkm/linuxkm_memory.c"
1845
#endif