wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers memory.c Source File

memory.c

00001 /* memory.c
00002  *
00003  * Copyright (C) 2006-2020 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 /* check old macros @wc_fips */
00030 #if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY)
00031     #define USE_WOLFSSL_MEMORY
00032 #endif
00033 #if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK)
00034     #define WOLFSSL_MALLOC_CHECK
00035 #endif
00036 
00037 
00038 /*
00039 Possible memory options:
00040  * NO_WOLFSSL_MEMORY:               Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY.
00041  * WOLFSSL_STATIC_MEMORY:           Turns on the use of static memory buffers and functions.
00042                                         This allows for using static memory instead of dynamic.
00043  * WOLFSSL_STATIC_ALIGN:            Define defaults to 16 to indicate static memory alignment.
00044  * HAVE_IO_POOL:                    Enables use of static thread safe memory pool for input/output buffers.
00045  * XMALLOC_OVERRIDE:                Allows override of the XMALLOC, XFREE and XREALLOC macros.
00046  * XMALLOC_USER:                    Allows custom XMALLOC, XFREE and XREALLOC functions to be defined.
00047  * WOLFSSL_NO_MALLOC:               Disables the fall-back case to use STDIO malloc/free when no callbacks are set.
00048  * WOLFSSL_TRACK_MEMORY:            Enables memory tracking for total stats and list of allocated memory.
00049  * WOLFSSL_DEBUG_MEMORY:            Enables extra function and line number args for memory callbacks.
00050  * WOLFSSL_DEBUG_MEMORY_PRINT:      Enables printing of each malloc/free.
00051  * WOLFSSL_MALLOC_CHECK:            Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
00052  * WOLFSSL_FORCE_MALLOC_FAIL_TEST:  Used for internal testing to induce random malloc failures.
00053  * WOLFSSL_HEAP_TEST:               Used for internal testing of heap hint
00054  */
00055 
00056 #ifdef WOLFSSL_ZEPHYR
00057 #undef realloc
00058 void *z_realloc(void *ptr, size_t size)
00059 {
00060     if (ptr == NULL)
00061         ptr = malloc(size);
00062     else
00063         ptr = realloc(ptr, size);
00064 
00065     return ptr;
00066 }
00067 #define realloc z_realloc
00068 #endif
00069 
00070 #ifdef USE_WOLFSSL_MEMORY
00071 
00072 #include <wolfssl/wolfcrypt/memory.h >
00073 #include <wolfssl/wolfcrypt/error-crypt.h >
00074 #include <wolfssl/wolfcrypt/logging.h >
00075 
00076 #if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT)
00077 #include <stdio.h>
00078 #endif
00079 
00080 #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
00081     static int gMemFailCountSeed;
00082     static int gMemFailCount;
00083     void wolfSSL_SetMemFailCount(int memFailCount)
00084     {
00085         if (gMemFailCountSeed == 0) {
00086             gMemFailCountSeed = memFailCount;
00087             gMemFailCount = memFailCount;
00088         }
00089     }
00090 #endif
00091 #if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \
00092                                                      defined(WOLFSSL_MEMORY_LOG)
00093     #include <stdio.h>
00094 #endif
00095 
00096 
00097 /* Set these to default values initially. */
00098 static wolfSSL_Malloc_cb  malloc_function = NULL;
00099 static wolfSSL_Free_cb    free_function = NULL;
00100 static wolfSSL_Realloc_cb realloc_function = NULL;
00101 
00102 int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
00103                           wolfSSL_Free_cb    ff,
00104                           wolfSSL_Realloc_cb rf)
00105 {
00106     malloc_function = mf;
00107     free_function = ff;
00108     realloc_function = rf;
00109     return 0;
00110 }
00111 
00112 int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
00113                           wolfSSL_Free_cb*    ff,
00114                           wolfSSL_Realloc_cb* rf)
00115 {
00116     if (mf) *mf = malloc_function;
00117     if (ff) *ff = free_function;
00118     if (rf) *rf = realloc_function;
00119     return 0;
00120 }
00121 
00122 #ifndef WOLFSSL_STATIC_MEMORY
00123 #ifdef WOLFSSL_DEBUG_MEMORY
00124 void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
00125 #else
00126 void* wolfSSL_Malloc(size_t size)
00127 #endif
00128 {
00129     void* res = 0;
00130 
00131     if (malloc_function) {
00132     #ifdef WOLFSSL_DEBUG_MEMORY
00133         res = malloc_function(size, func, line);
00134     #else
00135         res = malloc_function(size);
00136     #endif
00137     }
00138     else {
00139     #ifndef WOLFSSL_NO_MALLOC
00140         res = malloc(size);
00141     #else
00142         WOLFSSL_MSG("No malloc available");
00143     #endif
00144     }
00145 
00146 #ifdef WOLFSSL_DEBUG_MEMORY
00147 #if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
00148     printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line);
00149 #else
00150     (void)func;
00151     (void)line;
00152 #endif
00153 #endif
00154 
00155 #ifdef WOLFSSL_MALLOC_CHECK
00156     if (res == NULL)
00157         WOLFSSL_MSG("wolfSSL_malloc failed");
00158 #endif
00159 
00160 #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
00161     if (res && --gMemFailCount == 0) {
00162         printf("\n---FORCED MEM FAIL TEST---\n");
00163         if (free_function) {
00164         #ifdef WOLFSSL_DEBUG_MEMORY
00165             free_function(res, func, line);
00166         #else
00167             free_function(res);
00168         #endif
00169         }
00170         else {
00171             free(res); /* clear */
00172         }
00173         gMemFailCount = gMemFailCountSeed; /* reset */
00174         return NULL;
00175     }
00176 #endif
00177 
00178     return res;
00179 }
00180 
00181 #ifdef WOLFSSL_DEBUG_MEMORY
00182 void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
00183 #else
00184 void wolfSSL_Free(void *ptr)
00185 #endif
00186 {
00187 #ifdef WOLFSSL_DEBUG_MEMORY
00188 #if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
00189     printf("Free: %p at %s:%d\n", ptr, func, line);
00190 #else
00191     (void)func;
00192     (void)line;
00193 #endif
00194 #endif
00195 
00196     if (free_function) {
00197     #ifdef WOLFSSL_DEBUG_MEMORY
00198         free_function(ptr, func, line);
00199     #else
00200         free_function(ptr);
00201     #endif
00202     }
00203     else {
00204     #ifndef WOLFSSL_NO_MALLOC
00205         free(ptr);
00206     #else
00207         WOLFSSL_MSG("No free available");
00208     #endif
00209     }
00210 }
00211 
00212 #ifdef WOLFSSL_DEBUG_MEMORY
00213 void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
00214 #else
00215 void* wolfSSL_Realloc(void *ptr, size_t size)
00216 #endif
00217 {
00218     void* res = 0;
00219 
00220     if (realloc_function) {
00221     #ifdef WOLFSSL_DEBUG_MEMORY
00222         res = realloc_function(ptr, size, func, line);
00223     #else
00224         res = realloc_function(ptr, size);
00225     #endif
00226     }
00227     else {
00228     #ifndef WOLFSSL_NO_MALLOC
00229         res = realloc(ptr, size);
00230     #else
00231         WOLFSSL_MSG("No realloc available");
00232     #endif
00233     }
00234 
00235     return res;
00236 }
00237 #endif /* WOLFSSL_STATIC_MEMORY */
00238 
00239 #ifdef WOLFSSL_STATIC_MEMORY
00240 
00241 struct wc_Memory {
00242     byte*  buffer;
00243     struct wc_Memory* next;
00244     word32 sz;
00245 };
00246 
00247 
00248 /* returns amount of memory used on success. On error returns negative value
00249    wc_Memory** list is the list that new buckets are prepended to
00250  */
00251 static int create_memory_buckets(byte* buffer, word32 bufSz,
00252                               word32 buckSz, word32 buckNum, wc_Memory** list) {
00253     word32 i;
00254     byte*  pt  = buffer;
00255     int    ret = 0;
00256     word32 memSz = (word32)sizeof(wc_Memory);
00257     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00258 
00259     /* if not enough space available for bucket size then do not try */
00260     if (buckSz + memSz + padSz > bufSz) {
00261         return ret;
00262     }
00263 
00264     for (i = 0; i < buckNum; i++) {
00265         if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
00266             /* create a new struct and set its values */
00267             wc_Memory* mem = (struct wc_Memory*)(pt);
00268             mem->sz = buckSz;
00269             mem->buffer = (byte*)pt + padSz + memSz;
00270             mem->next = NULL;
00271 
00272             /* add the newly created struct to front of list */
00273             if (*list == NULL) {
00274                 *list = mem;
00275             } else {
00276                 mem->next = *list;
00277                 *list = mem;
00278             }
00279 
00280             /* advance pointer and keep track of memory used */
00281             ret += buckSz + padSz + memSz;
00282             pt  += buckSz + padSz + memSz;
00283         }
00284         else {
00285             break; /* not enough space left for more buckets of this size */
00286         }
00287     }
00288 
00289     return ret;
00290 }
00291 
00292 int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
00293 {
00294     word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
00295     word32 wc_Dist[WOLFMEM_DEF_BUCKETS]  = { WOLFMEM_DIST };
00296 
00297     if (heap == NULL) {
00298         return BAD_FUNC_ARG;
00299     }
00300 
00301     XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
00302 
00303     XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
00304     XMEMCPY(heap->distList, wc_Dist,  sizeof(wc_Dist));
00305 
00306     if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
00307         WOLFSSL_MSG("Error creating heap memory mutex");
00308         return BAD_MUTEX_E;
00309     }
00310 
00311     return 0;
00312 }
00313 
00314 int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
00315     unsigned char* buf, unsigned int sz, int flag, int max)
00316 {
00317     int ret;
00318     WOLFSSL_HEAP*      heap;
00319     WOLFSSL_HEAP_HINT* hint;
00320     word32 idx = 0;
00321 
00322     if (pHint == NULL || buf == NULL) {
00323         return BAD_FUNC_ARG;
00324     }
00325 
00326     if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
00327         return BUFFER_E; /* not enough memory for structures */
00328     }
00329 
00330     /* check if hint has already been assigned */
00331     if (*pHint == NULL) {
00332         heap = (WOLFSSL_HEAP*)buf;
00333         idx += sizeof(WOLFSSL_HEAP);
00334         hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
00335         idx += sizeof(WOLFSSL_HEAP_HINT);
00336 
00337         ret = wolfSSL_init_memory_heap(heap);
00338         if (ret != 0) {
00339             return ret;
00340         }
00341 
00342         XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
00343         hint->memory = heap;
00344     }
00345     else {
00346     #ifdef WOLFSSL_HEAP_TEST
00347         /* do not load in memory if test has been set */
00348         if (heap == (void*)WOLFSSL_HEAP_TEST) {
00349             return 0;
00350         }
00351     #endif
00352 
00353         hint = (WOLFSSL_HEAP_HINT*)(*pHint);
00354         heap = hint->memory;
00355     }
00356 
00357     ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
00358     if (ret != 1) {
00359         WOLFSSL_MSG("Error partitioning memory");
00360         return -1;
00361     }
00362 
00363     /* determine what max applies too */
00364     if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
00365         heap->maxIO = max;
00366     }
00367     else { /* general memory used in handshakes */
00368         heap->maxHa = max;
00369     }
00370 
00371     heap->flag |= flag;
00372     *pHint = hint;
00373 
00374     (void)max;
00375 
00376     return 0;
00377 }
00378 
00379 int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
00380                                                              WOLFSSL_HEAP* heap)
00381 {
00382     word32 ava = sz;
00383     byte*  pt  = buffer;
00384     int    ret = 0;
00385     word32 memSz = (word32)sizeof(wc_Memory);
00386     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00387 
00388     WOLFSSL_ENTER("wolfSSL_load_static_memory");
00389 
00390     if (buffer == NULL) {
00391         return BAD_FUNC_ARG;
00392     }
00393 
00394     /* align pt */
00395     while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
00396         *pt = 0x00;
00397         pt++;
00398         ava--;
00399     }
00400 
00401 #ifdef WOLFSSL_DEBUG_MEMORY
00402     printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
00403 #endif
00404 
00405     /* divide into chunks of memory and add them to available list */
00406     while (ava >= (heap->sizeList[0] + padSz + memSz)) {
00407         int i;
00408         /* creating only IO buffers from memory passed in, max TLS is 16k */
00409         if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
00410             if ((ret = create_memory_buckets(pt, ava,
00411                                           WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
00412                 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
00413                 return ret;
00414             }
00415 
00416             /* check if no more room left for creating IO buffers */
00417             if (ret == 0) {
00418                 break;
00419             }
00420 
00421             /* advance pointer in buffer for next buckets and keep track
00422                of how much memory is left available */
00423             pt  += ret;
00424             ava -= ret;
00425         }
00426         else {
00427             /* start at largest and move to smaller buckets */
00428             for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
00429                 if ((heap->sizeList[i] + padSz + memSz) <= ava) {
00430                     if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
00431                                      heap->distList[i], &(heap->ava[i]))) < 0) {
00432                         WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
00433                         return ret;
00434                     }
00435 
00436                     /* advance pointer in buffer for next buckets and keep track
00437                        of how much memory is left available */
00438                     pt  += ret;
00439                     ava -= ret;
00440                 }
00441             }
00442         }
00443     }
00444 
00445     return 1;
00446 }
00447 
00448 
00449 /* returns the size of management memory needed for each bucket.
00450  * This is memory that is used to keep track of and align memory buckets. */
00451 int wolfSSL_MemoryPaddingSz(void)
00452 {
00453     word32 memSz = (word32)sizeof(wc_Memory);
00454     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00455     return memSz + padSz;
00456 }
00457 
00458 
00459 /* Used to calculate memory size for optimum use with buckets.
00460    returns the suggested size rounded down to the nearest bucket. */
00461 int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
00462 {
00463     word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
00464     word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
00465 
00466     word32 ava = sz;
00467     byte*  pt  = buffer;
00468     word32 memSz = (word32)sizeof(wc_Memory);
00469     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00470 
00471     WOLFSSL_ENTER("wolfSSL_static_size");
00472 
00473     if (buffer == NULL) {
00474         return BAD_FUNC_ARG;
00475     }
00476 
00477     /* align pt */
00478     while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
00479         pt++;
00480         ava--;
00481     }
00482 
00483     /* creating only IO buffers from memory passed in, max TLS is 16k */
00484     if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
00485         if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
00486             return 0; /* not enough room for even one bucket */
00487         }
00488 
00489         ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
00490     }
00491     else {
00492         int i, k;
00493 
00494         if (ava < (bucketSz[0] + padSz + memSz)) {
00495             return 0; /* not enough room for even one bucket */
00496         }
00497 
00498         while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
00499             /* start at largest and move to smaller buckets */
00500             for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
00501                 for (k = distList[i]; k > 0; k--) {
00502                     if ((bucketSz[i] + padSz + memSz) <= ava) {
00503                         ava -= bucketSz[i] + padSz + memSz;
00504                     }
00505                 }
00506             }
00507         }
00508     }
00509 
00510     return sz - ava; /* round down */
00511 }
00512 
00513 
00514 int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
00515 {
00516     WOLFSSL_MSG("Freeing fixed IO buffer");
00517 
00518     /* check if fixed buffer was set */
00519     if (*io == NULL) {
00520         return 1;
00521     }
00522 
00523     if (heap == NULL) {
00524         WOLFSSL_MSG("No heap to return fixed IO too");
00525     }
00526     else {
00527         /* put IO buffer back into IO pool */
00528         (*io)->next = heap->io;
00529         heap->io    = *io;
00530         *io         = NULL;
00531     }
00532 
00533     return 1;
00534 }
00535 
00536 
00537 int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
00538 {
00539     WOLFSSL_MSG("Setting fixed IO for SSL");
00540     if (heap == NULL) {
00541         return MEMORY_E;
00542     }
00543 
00544     *io = heap->io;
00545 
00546     if (*io != NULL) {
00547         heap->io = (*io)->next;
00548         (*io)->next = NULL;
00549     }
00550     else { /* failed to grab an IO buffer */
00551         return 0;
00552     }
00553 
00554     return 1;
00555 }
00556 
00557 
00558 int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
00559 {
00560         word32     i;
00561         wc_Memory* pt;
00562 
00563         XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
00564 
00565         stats->totalAlloc = heap->alloc;
00566         stats->totalFr    = heap->frAlc;
00567         stats->curAlloc   = stats->totalAlloc - stats->totalFr;
00568         stats->maxHa      = heap->maxHa;
00569         stats->maxIO      = heap->maxIO;
00570         for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00571             stats->blockSz[i] = heap->sizeList[i];
00572             for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
00573                 stats->avaBlock[i] += 1;
00574             }
00575         }
00576 
00577         for (pt = heap->io; pt != NULL; pt = pt->next) {
00578             stats->avaIO++;
00579         }
00580 
00581         stats->flag       = heap->flag; /* flag used */
00582 
00583     return 1;
00584 }
00585 
00586 
00587 #ifdef WOLFSSL_DEBUG_MEMORY
00588 void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
00589 #else
00590 void* wolfSSL_Malloc(size_t size, void* heap, int type)
00591 #endif
00592 {
00593     void* res = 0;
00594     wc_Memory* pt = NULL;
00595     int   i;
00596 
00597     /* check for testing heap hint was set */
00598 #ifdef WOLFSSL_HEAP_TEST
00599     if (heap == (void*)WOLFSSL_HEAP_TEST) {
00600         return malloc(size);
00601     }
00602 #endif
00603 
00604     /* if no heap hint then use dynamic memory*/
00605     if (heap == NULL) {
00606         #ifdef WOLFSSL_HEAP_TEST
00607             /* allow using malloc for creating ctx and method */
00608             if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
00609                                             type == DYNAMIC_TYPE_CERT_MANAGER) {
00610                 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
00611                 res = malloc(size);
00612             }
00613             else {
00614                 WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n");
00615                 res = NULL;
00616             }
00617         #else
00618         #ifndef WOLFSSL_NO_MALLOC
00619             #ifdef FREERTOS
00620                 res = pvPortMalloc(size);
00621             #else
00622                 res = malloc(size);
00623             #endif
00624         #else
00625             WOLFSSL_MSG("No heap hint found to use and no malloc");
00626             #ifdef WOLFSSL_DEBUG_MEMORY
00627             printf("ERROR: at %s:%d\n", func, line);
00628             #endif
00629         #endif /* WOLFSSL_NO_MALLOC */
00630         #endif /* WOLFSSL_HEAP_TEST */
00631     }
00632     else {
00633         WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00634         WOLFSSL_HEAP*      mem  = hint->memory;
00635 
00636         if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00637             WOLFSSL_MSG("Bad memory_mutex lock");
00638             return NULL;
00639         }
00640 
00641         /* case of using fixed IO buffers */
00642         if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
00643                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00644                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00645             if (type == DYNAMIC_TYPE_OUT_BUFFER) {
00646                 pt = hint->outBuf;
00647             }
00648             if (type == DYNAMIC_TYPE_IN_BUFFER) {
00649                 pt = hint->inBuf;
00650             }
00651         }
00652         else {
00653             /* check if using IO pool flag */
00654             if (mem->flag & WOLFMEM_IO_POOL &&
00655                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00656                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00657                 if (mem->io != NULL) {
00658                     pt      = mem->io;
00659                     mem->io = pt->next;
00660                 }
00661             }
00662 
00663             /* general static memory */
00664             if (pt == NULL) {
00665                 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00666                     if ((word32)size < mem->sizeList[i]) {
00667                         if (mem->ava[i] != NULL) {
00668                             pt = mem->ava[i];
00669                             mem->ava[i] = pt->next;
00670                             break;
00671                         }
00672                     #ifdef WOLFSSL_DEBUG_STATIC_MEMORY
00673                         else {
00674                             printf("Size: %ld, Empty: %d\n", size,
00675                                                               mem->sizeList[i]);
00676                         }
00677                     #endif
00678                     }
00679                 }
00680             }
00681         }
00682 
00683         if (pt != NULL) {
00684             mem->inUse += pt->sz;
00685             mem->alloc += 1;
00686             res = pt->buffer;
00687 
00688         #ifdef WOLFSSL_DEBUG_MEMORY
00689             printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
00690         #endif
00691 
00692             /* keep track of connection statistics if flag is set */
00693             if (mem->flag & WOLFMEM_TRACK_STATS) {
00694                 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
00695                 if (stats != NULL) {
00696                     stats->curMem += pt->sz;
00697                     if (stats->peakMem < stats->curMem) {
00698                         stats->peakMem = stats->curMem;
00699                     }
00700                     stats->curAlloc++;
00701                     if (stats->peakAlloc < stats->curAlloc) {
00702                         stats->peakAlloc = stats->curAlloc;
00703                     }
00704                     stats->totalAlloc++;
00705                 }
00706             }
00707         }
00708         else {
00709             WOLFSSL_MSG("ERROR ran out of static memory");
00710             #ifdef WOLFSSL_DEBUG_MEMORY
00711             printf("Looking for %lu bytes at %s:%d\n", size, func, line);
00712             #endif
00713         }
00714 
00715         wc_UnLockMutex(&(mem->memory_mutex));
00716     }
00717 
00718     #ifdef WOLFSSL_MALLOC_CHECK
00719         if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
00720             WOLFSSL_MSG("ERROR memory is not aligned");
00721             res = NULL;
00722         }
00723     #endif
00724 
00725 
00726     (void)i;
00727     (void)pt;
00728     (void)type;
00729 
00730     return res;
00731 }
00732 
00733 
00734 #ifdef WOLFSSL_DEBUG_MEMORY
00735 void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
00736 #else
00737 void wolfSSL_Free(void *ptr, void* heap, int type)
00738 #endif
00739 {
00740     int i;
00741     wc_Memory* pt;
00742 
00743     if (ptr) {
00744         /* check for testing heap hint was set */
00745     #ifdef WOLFSSL_HEAP_TEST
00746         if (heap == (void*)WOLFSSL_HEAP_TEST) {
00747             return free(ptr);
00748         }
00749     #endif
00750 
00751         if (heap == NULL) {
00752         #ifdef WOLFSSL_HEAP_TEST
00753             /* allow using malloc for creating ctx and method */
00754             if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
00755                                             type == DYNAMIC_TYPE_CERT_MANAGER) {
00756                 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
00757             }
00758             else {
00759                 WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n");
00760             }
00761         #endif
00762         #ifndef WOLFSSL_NO_MALLOC
00763             #ifdef FREERTOS
00764                 vPortFree(ptr);
00765             #else
00766                 free(ptr);
00767             #endif
00768         #else
00769             WOLFSSL_MSG("Error trying to call free when turned off");
00770         #endif /* WOLFSSL_NO_MALLOC */
00771         }
00772         else {
00773             WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00774             WOLFSSL_HEAP*      mem  = hint->memory;
00775             word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
00776 
00777             /* get memory struct and add it to available list */
00778             pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
00779             if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00780                 WOLFSSL_MSG("Bad memory_mutex lock");
00781                 return;
00782             }
00783 
00784             /* case of using fixed IO buffers */
00785             if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
00786                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00787                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00788                 /* fixed IO pools are free'd at the end of SSL lifetime
00789                    using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
00790             }
00791             else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
00792                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00793                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00794                 pt->next = mem->io;
00795                 mem->io  = pt;
00796             }
00797             else { /* general memory free */
00798                 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00799                     if (pt->sz == mem->sizeList[i]) {
00800                         pt->next = mem->ava[i];
00801                         mem->ava[i] = pt;
00802                         break;
00803                     }
00804                 }
00805             }
00806             mem->inUse -= pt->sz;
00807             mem->frAlc += 1;
00808 
00809         #ifdef WOLFSSL_DEBUG_MEMORY
00810             printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
00811         #endif
00812 
00813             /* keep track of connection statistics if flag is set */
00814             if (mem->flag & WOLFMEM_TRACK_STATS) {
00815                 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
00816                 if (stats != NULL) {
00817                     /* avoid under flow */
00818                     if (stats->curMem > pt->sz) {
00819                         stats->curMem -= pt->sz;
00820                     }
00821                     else {
00822                         stats->curMem = 0;
00823                     }
00824 
00825                     if (stats->curAlloc > 0) {
00826                         stats->curAlloc--;
00827                     }
00828                     stats->totalFr++;
00829                 }
00830             }
00831             wc_UnLockMutex(&(mem->memory_mutex));
00832         }
00833     }
00834 
00835     (void)i;
00836     (void)pt;
00837     (void)type;
00838 }
00839 
00840 #ifdef WOLFSSL_DEBUG_MEMORY
00841 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
00842 #else
00843 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
00844 #endif
00845 {
00846     void* res = 0;
00847     wc_Memory* pt = NULL;
00848     word32 prvSz;
00849     int    i;
00850 
00851     /* check for testing heap hint was set */
00852 #ifdef WOLFSSL_HEAP_TEST
00853     if (heap == (void*)WOLFSSL_HEAP_TEST) {
00854         return realloc(ptr, size);
00855     }
00856 #endif
00857 
00858     if (heap == NULL) {
00859         #ifdef WOLFSSL_HEAP_TEST
00860             WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n");
00861         #endif
00862         #ifndef WOLFSSL_NO_MALLOC
00863             res = realloc(ptr, size);
00864         #else
00865             WOLFSSL_MSG("NO heap found to use for realloc");
00866         #endif /* WOLFSSL_NO_MALLOC */
00867     }
00868     else {
00869         WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00870         WOLFSSL_HEAP*      mem  = hint->memory;
00871         word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
00872 
00873         if (ptr == NULL) {
00874         #ifdef WOLFSSL_DEBUG_MEMORY
00875             return wolfSSL_Malloc(size, heap, type, func, line);
00876         #else
00877             return wolfSSL_Malloc(size, heap, type);
00878         #endif
00879         }
00880 
00881         if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00882             WOLFSSL_MSG("Bad memory_mutex lock");
00883             return NULL;
00884         }
00885 
00886         /* case of using fixed IO buffers or IO pool */
00887         if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
00888                                           && (type == DYNAMIC_TYPE_OUT_BUFFER ||
00889                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00890             /* no realloc, is fixed size */
00891             pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
00892             if (pt->sz < size) {
00893                 WOLFSSL_MSG("Error IO memory was not large enough");
00894                 res = NULL; /* return NULL in error case */
00895             }
00896             res = pt->buffer;
00897         }
00898         else {
00899         /* general memory */
00900             for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00901                 if ((word32)size < mem->sizeList[i]) {
00902                     if (mem->ava[i] != NULL) {
00903                         pt = mem->ava[i];
00904                         mem->ava[i] = pt->next;
00905                         break;
00906                     }
00907                 }
00908             }
00909 
00910             if (pt != NULL && res == NULL) {
00911                 res = pt->buffer;
00912 
00913                 /* copy over original information and free ptr */
00914                 prvSz = ((wc_Memory*)((byte*)ptr - padSz -
00915                                                sizeof(wc_Memory)))->sz;
00916                 prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
00917                 XMEMCPY(pt->buffer, ptr, prvSz);
00918                 mem->inUse += pt->sz;
00919                 mem->alloc += 1;
00920 
00921                 /* free memory that was previously being used */
00922                 wc_UnLockMutex(&(mem->memory_mutex));
00923                 wolfSSL_Free(ptr, heap, type
00924             #ifdef WOLFSSL_DEBUG_MEMORY
00925                     , func, line
00926             #endif
00927                 );
00928                 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00929                     WOLFSSL_MSG("Bad memory_mutex lock");
00930                     return NULL;
00931                 }
00932             }
00933         }
00934         wc_UnLockMutex(&(mem->memory_mutex));
00935     }
00936 
00937     #ifdef WOLFSSL_MALLOC_CHECK
00938         if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
00939             WOLFSSL_MSG("ERROR memory is not aligned");
00940             res = NULL;
00941         }
00942     #endif
00943 
00944     (void)i;
00945     (void)pt;
00946     (void)type;
00947 
00948     return res;
00949 }
00950 #endif /* WOLFSSL_STATIC_MEMORY */
00951 
00952 #endif /* USE_WOLFSSL_MEMORY */
00953 
00954 
00955 #ifdef HAVE_IO_POOL
00956 
00957 /* Example for user io pool, shared build may need definitions in lib proper */
00958 
00959 #include <wolfssl/wolfcrypt/types.h >
00960 #include <stdlib.h>
00961 
00962 #ifndef HAVE_THREAD_LS
00963     #error "Oops, simple I/O pool example needs thread local storage"
00964 #endif
00965 
00966 
00967 /* allow simple per thread in and out pools */
00968 /* use 17k size since max record size is 16k plus overhead */
00969 static THREAD_LS_T byte pool_in[17*1024];
00970 static THREAD_LS_T byte pool_out[17*1024];
00971 
00972 
00973 void* XMALLOC(size_t n, void* heap, int type)
00974 {
00975     (void)heap;
00976 
00977     if (type == DYNAMIC_TYPE_IN_BUFFER) {
00978         if (n < sizeof(pool_in))
00979             return pool_in;
00980         else
00981             return NULL;
00982     }
00983 
00984     if (type == DYNAMIC_TYPE_OUT_BUFFER) {
00985         if (n < sizeof(pool_out))
00986             return pool_out;
00987         else
00988             return NULL;
00989     }
00990 
00991     return malloc(n);
00992 }
00993 
00994 void* XREALLOC(void *p, size_t n, void* heap, int type)
00995 {
00996     (void)heap;
00997 
00998     if (type == DYNAMIC_TYPE_IN_BUFFER) {
00999         if (n < sizeof(pool_in))
01000             return pool_in;
01001         else
01002             return NULL;
01003     }
01004 
01005     if (type == DYNAMIC_TYPE_OUT_BUFFER) {
01006         if (n < sizeof(pool_out))
01007             return pool_out;
01008         else
01009             return NULL;
01010     }
01011 
01012     return realloc(p, n);
01013 }
01014 
01015 void XFREE(void *p, void* heap, int type)
01016 {
01017     (void)heap;
01018 
01019     if (type == DYNAMIC_TYPE_IN_BUFFER)
01020         return;  /* do nothing, static pool */
01021 
01022     if (type == DYNAMIC_TYPE_OUT_BUFFER)
01023         return;  /* do nothing, static pool */
01024 
01025     free(p);
01026 }
01027 
01028 #endif /* HAVE_IO_POOL */
01029 
01030 #ifdef WOLFSSL_MEMORY_LOG
01031 void *xmalloc(size_t n, void* heap, int type, const char* func,
01032               const char* file, unsigned int line)
01033 {
01034     void*   p;
01035     word32* p32;
01036 
01037     if (malloc_function)
01038         p32 = malloc_function(n + sizeof(word32) * 4);
01039     else
01040         p32 = malloc(n + sizeof(word32) * 4);
01041 
01042     p32[0] = (word32)n;
01043     p = (void*)(p32 + 4);
01044 
01045     fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, type,
01046                                                               func, file, line);
01047 
01048     (void)heap;
01049 
01050     return p;
01051 }
01052 void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
01053                const char* file, unsigned int line)
01054 {
01055     void*   newp = NULL;
01056     word32* p32;
01057     word32* oldp32 = NULL;
01058     word32  oldLen;
01059 
01060     if (p != NULL) {
01061         oldp32 = (word32*)p;
01062         oldp32 -= 4;
01063         oldLen = oldp32[0];
01064     }
01065 
01066     if (realloc_function)
01067         p32 = realloc_function(oldp32, n + sizeof(word32) * 4);
01068     else
01069         p32 = realloc(oldp32, n + sizeof(word32) * 4);
01070 
01071     if (p32 != NULL) {
01072         p32[0] = (word32)n;
01073         newp = (void*)(p32 + 4);
01074 
01075         fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n,
01076                                                         type, func, file, line);
01077         if (p != NULL) {
01078             fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen,
01079                                                         type, func, file, line);
01080         }
01081     }
01082 
01083     (void)heap;
01084 
01085     return newp;
01086 }
01087 void xfree(void *p, void* heap, int type, const char* func, const char* file,
01088            unsigned int line)
01089 {
01090     word32* p32 = (word32*)p;
01091 
01092     if (p != NULL) {
01093         p32 -= 4;
01094 
01095         fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,
01096                                                               func, file, line);
01097 
01098         if (free_function)
01099             free_function(p32);
01100         else
01101             free(p32);
01102     }
01103 
01104     (void)heap;
01105 }
01106 #endif /* WOLFSSL_MEMORY_LOG */
01107 
01108 #ifdef WOLFSSL_STACK_LOG
01109 /* Note: this code only works with GCC using -finstrument-functions. */
01110 void __attribute__((no_instrument_function))
01111      __cyg_profile_func_enter(void *func,  void *caller)
01112 {
01113     register void* sp asm("sp");
01114     fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(size_t)func, sp);
01115     (void)caller;
01116 }
01117 
01118 void __attribute__((no_instrument_function))
01119      __cyg_profile_func_exit(void *func, void *caller)
01120 {
01121     register void* sp asm("sp");
01122     fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(size_t)func, sp);
01123     (void)caller;
01124 }
01125 #endif
01126 
01127