Coverage Report

Created: 2025-07-04 06:22

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