Xuyi Wang / wolfcrypt

Dependents:   OS

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-2017 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 <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 #ifdef USE_WOLFSSL_MEMORY
00038 
00039 #include <wolfcrypt/memory.h>
00040 #include <wolfcrypt/error-crypt.h>
00041 #include <wolfcrypt/logging.h>
00042 
00043 #if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL)
00044     #include <stdio.h>
00045 #endif
00046 
00047 
00048 /* Set these to default values initially. */
00049 static wolfSSL_Malloc_cb  malloc_function = NULL;
00050 static wolfSSL_Free_cb    free_function = NULL;
00051 static wolfSSL_Realloc_cb realloc_function = NULL;
00052 
00053 int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
00054                           wolfSSL_Free_cb    ff,
00055                           wolfSSL_Realloc_cb rf)
00056 {
00057     int res = 0;
00058 
00059     if (mf)
00060         malloc_function = mf;
00061     else
00062         res = BAD_FUNC_ARG;
00063 
00064     if (ff)
00065         free_function = ff;
00066     else
00067         res = BAD_FUNC_ARG;
00068 
00069     if (rf)
00070         realloc_function = rf;
00071     else
00072         res = BAD_FUNC_ARG;
00073 
00074     return res;
00075 }
00076 
00077 int wolfSSL_ResetAllocators(void)
00078 {
00079     /* allow nulls to be set for callbacks to restore defaults */
00080     malloc_function = NULL;
00081     free_function = NULL;
00082     realloc_function = NULL;
00083 
00084     return 0;
00085 }
00086 
00087 int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
00088                           wolfSSL_Free_cb*    ff,
00089                           wolfSSL_Realloc_cb* rf)
00090 {
00091     if (mf) *mf = malloc_function;
00092     if (ff) *ff = free_function;
00093     if (rf) *rf = realloc_function;
00094     return 0;
00095 }
00096 
00097 #ifndef WOLFSSL_STATIC_MEMORY
00098 #ifdef WOLFSSL_DEBUG_MEMORY
00099 void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
00100 #else
00101 void* wolfSSL_Malloc(size_t size)
00102 #endif
00103 {
00104     void* res = 0;
00105 
00106     if (malloc_function) {
00107     #ifdef WOLFSSL_DEBUG_MEMORY
00108         res = malloc_function(size, func, line);
00109     #else
00110         res = malloc_function(size);
00111     #endif
00112     }
00113     else {
00114     #ifndef WOLFSSL_NO_MALLOC
00115         res = malloc(size);
00116     #else
00117         WOLFSSL_MSG("No malloc available");
00118     #endif
00119     }
00120 
00121     #ifdef WOLFSSL_MALLOC_CHECK
00122         if (res == NULL)
00123             puts("wolfSSL_malloc failed");
00124     #endif
00125 
00126     return res;
00127 }
00128 
00129 #ifdef WOLFSSL_DEBUG_MEMORY
00130 void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
00131 #else
00132 void wolfSSL_Free(void *ptr)
00133 #endif
00134 {
00135     if (free_function) {
00136     #ifdef WOLFSSL_DEBUG_MEMORY
00137         free_function(ptr, func, line);
00138     #else
00139         free_function(ptr);
00140     #endif
00141     }
00142     else {
00143     #ifndef WOLFSSL_NO_MALLOC
00144         free(ptr);
00145     #else
00146         WOLFSSL_MSG("No free available");
00147     #endif
00148     }
00149 }
00150 
00151 #ifdef WOLFSSL_DEBUG_MEMORY
00152 void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
00153 #else
00154 void* wolfSSL_Realloc(void *ptr, size_t size)
00155 #endif
00156 {
00157     void* res = 0;
00158 
00159     if (realloc_function) {
00160     #ifdef WOLFSSL_DEBUG_MEMORY
00161         res = realloc_function(ptr, size, func, line);
00162     #else
00163         res = realloc_function(ptr, size);
00164     #endif
00165     }
00166     else {
00167     #ifndef WOLFSSL_NO_MALLOC
00168         res = realloc(ptr, size);
00169     #else
00170         WOLFSSL_MSG("No realloc available");
00171     #endif
00172     }
00173 
00174     return res;
00175 }
00176 #endif /* WOLFSSL_STATIC_MEMORY */
00177 
00178 #ifdef WOLFSSL_STATIC_MEMORY
00179 
00180 struct wc_Memory {
00181     byte*  buffer;
00182     struct wc_Memory* next;
00183     word32 sz;
00184 };
00185 
00186 
00187 /* returns amount of memory used on success. On error returns negative value
00188    wc_Memory** list is the list that new buckets are prepended to
00189  */
00190 static int create_memory_buckets(byte* buffer, word32 bufSz,
00191                               word32 buckSz, word32 buckNum, wc_Memory** list) {
00192     word32 i;
00193     byte*  pt  = buffer;
00194     int    ret = 0;
00195     word32 memSz = (word32)sizeof(wc_Memory);
00196     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00197 
00198     /* if not enough space available for bucket size then do not try */
00199     if (buckSz + memSz + padSz > bufSz) {
00200         return ret;
00201     }
00202 
00203     for (i = 0; i < buckNum; i++) {
00204         if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
00205             /* create a new struct and set its values */
00206             wc_Memory* mem = (struct wc_Memory*)(pt);
00207             mem->sz = buckSz;
00208             mem->buffer = (byte*)pt + padSz + memSz;
00209             mem->next = NULL;
00210 
00211             /* add the newly created struct to front of list */
00212             if (*list == NULL) {
00213                 *list = mem;
00214             } else {
00215                 mem->next = *list;
00216                 *list = mem;
00217             }
00218 
00219             /* advance pointer and keep track of memory used */
00220             ret += buckSz + padSz + memSz;
00221             pt  += buckSz + padSz + memSz;
00222         }
00223         else {
00224             break; /* not enough space left for more buckets of this size */
00225         }
00226     }
00227 
00228     return ret;
00229 }
00230 
00231 int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
00232 {
00233     word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
00234     word32 wc_Dist[WOLFMEM_DEF_BUCKETS]  = { WOLFMEM_DIST };
00235 
00236     if (heap == NULL) {
00237         return BAD_FUNC_ARG;
00238     }
00239 
00240     XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
00241 
00242     XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
00243     XMEMCPY(heap->distList, wc_Dist,  sizeof(wc_Dist));
00244 
00245     if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
00246         WOLFSSL_MSG("Error creating heap memory mutex");
00247         return BAD_MUTEX_E;
00248     }
00249 
00250     return 0;
00251 }
00252 
00253 int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
00254     unsigned char* buf, unsigned int sz, int flag, int max)
00255 {
00256     int ret;
00257     WOLFSSL_HEAP*      heap;
00258     WOLFSSL_HEAP_HINT* hint;
00259     word32 idx = 0;
00260 
00261     if (pHint == NULL || buf == NULL) {
00262         return BAD_FUNC_ARG;
00263     }
00264 
00265     if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
00266         return BUFFER_E; /* not enough memory for structures */
00267     }
00268 
00269     /* check if hint has already been assigned */
00270     if (*pHint == NULL) {
00271         heap = (WOLFSSL_HEAP*)buf;
00272         idx += sizeof(WOLFSSL_HEAP);
00273         hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
00274         idx += sizeof(WOLFSSL_HEAP_HINT);
00275 
00276         ret = wolfSSL_init_memory_heap(heap);
00277         if (ret != 0) {
00278             return ret;
00279         }
00280 
00281         XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
00282         hint->memory = heap;
00283     }
00284     else {
00285     #ifdef WOLFSSL_HEAP_TEST
00286         /* do not load in memory if test has been set */
00287         if (heap == (void*)WOLFSSL_HEAP_TEST) {
00288             return 0;
00289         }
00290     #endif
00291 
00292         hint = (WOLFSSL_HEAP_HINT*)(*pHint);
00293         heap = hint->memory;
00294     }
00295 
00296     ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
00297     if (ret != 1) {
00298         WOLFSSL_MSG("Error partitioning memory");
00299         return -1;
00300     }
00301 
00302     /* determine what max applies too */
00303     if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
00304         heap->maxIO = max;
00305     }
00306     else { /* general memory used in handshakes */
00307         heap->maxHa = max;
00308     }
00309 
00310     heap->flag |= flag;
00311     *pHint = hint;
00312 
00313     (void)max;
00314 
00315     return 0;
00316 }
00317 
00318 int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
00319                                                              WOLFSSL_HEAP* heap)
00320 {
00321     word32 ava = sz;
00322     byte*  pt  = buffer;
00323     int    ret = 0;
00324     word32 memSz = (word32)sizeof(wc_Memory);
00325     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00326 
00327     WOLFSSL_ENTER("wolfSSL_load_static_memory");
00328 
00329     if (buffer == NULL) {
00330         return BAD_FUNC_ARG;
00331     }
00332 
00333     /* align pt */
00334     while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
00335         *pt = 0x00;
00336         pt++;
00337         ava--;
00338     }
00339 
00340 #ifdef WOLFSSL_DEBUG_MEMORY
00341     printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
00342 #endif
00343 
00344     /* devide into chunks of memory and add them to available list */
00345     while (ava >= (heap->sizeList[0] + padSz + memSz)) {
00346         int i;
00347         /* creating only IO buffers from memory passed in, max TLS is 16k */
00348         if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
00349             if ((ret = create_memory_buckets(pt, ava,
00350                                           WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
00351                 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
00352                 return ret;
00353             }
00354 
00355             /* check if no more room left for creating IO buffers */
00356             if (ret == 0) {
00357                 break;
00358             }
00359 
00360             /* advance pointer in buffer for next buckets and keep track
00361                of how much memory is left available */
00362             pt  += ret;
00363             ava -= ret;
00364         }
00365         else {
00366             /* start at largest and move to smaller buckets */
00367             for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
00368                 if ((heap->sizeList[i] + padSz + memSz) <= ava) {
00369                     if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
00370                                      heap->distList[i], &(heap->ava[i]))) < 0) {
00371                         WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
00372                         return ret;
00373                     }
00374 
00375                     /* advance pointer in buffer for next buckets and keep track
00376                        of how much memory is left available */
00377                     pt  += ret;
00378                     ava -= ret;
00379                 }
00380             }
00381         }
00382     }
00383 
00384     return 1;
00385 }
00386 
00387 
00388 /* returns the size of management memory needed for each bucket.
00389  * This is memory that is used to keep track of and align memory buckets. */
00390 int wolfSSL_MemoryPaddingSz(void)
00391 {
00392     word32 memSz = (word32)sizeof(wc_Memory);
00393     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00394     return memSz + padSz;
00395 }
00396 
00397 
00398 /* Used to calculate memory size for optimum use with buckets.
00399    returns the suggested size rounded down to the nearest bucket. */
00400 int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
00401 {
00402     word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
00403     word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
00404 
00405     word32 ava = sz;
00406     byte*  pt  = buffer;
00407     word32 memSz = (word32)sizeof(wc_Memory);
00408     word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
00409 
00410     WOLFSSL_ENTER("wolfSSL_static_size");
00411 
00412     if (buffer == NULL) {
00413         return BAD_FUNC_ARG;
00414     }
00415 
00416     /* align pt */
00417     while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
00418         pt++;
00419         ava--;
00420     }
00421 
00422     /* creating only IO buffers from memory passed in, max TLS is 16k */
00423     if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
00424         if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
00425             return 0; /* not enough room for even one bucket */
00426         }
00427 
00428         ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
00429     }
00430     else {
00431         int i, k;
00432 
00433         if (ava < (bucketSz[0] + padSz + memSz)) {
00434             return 0; /* not enough room for even one bucket */
00435         }
00436 
00437         while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
00438             /* start at largest and move to smaller buckets */
00439             for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
00440                 for (k = distList[i]; k > 0; k--) {
00441                     if ((bucketSz[i] + padSz + memSz) <= ava) {
00442                         ava -= bucketSz[i] + padSz + memSz;
00443                     }
00444                 }
00445             }
00446         }
00447     }
00448 
00449     return sz - ava; /* round down */
00450 }
00451 
00452 
00453 int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
00454 {
00455     WOLFSSL_MSG("Freeing fixed IO buffer");
00456 
00457     /* check if fixed buffer was set */
00458     if (*io == NULL) {
00459         return 1;
00460     }
00461 
00462     if (heap == NULL) {
00463         WOLFSSL_MSG("No heap to return fixed IO too");
00464     }
00465     else {
00466         /* put IO buffer back into IO pool */
00467         (*io)->next = heap->io;
00468         heap->io    = *io;
00469         *io         = NULL;
00470     }
00471 
00472     return 1;
00473 }
00474 
00475 
00476 int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
00477 {
00478     WOLFSSL_MSG("Setting fixed IO for SSL");
00479     if (heap == NULL) {
00480         return MEMORY_E;
00481     }
00482 
00483     *io = heap->io;
00484 
00485     if (*io != NULL) {
00486         heap->io = (*io)->next;
00487         (*io)->next = NULL;
00488     }
00489     else { /* failed to grab an IO buffer */
00490         return 0;
00491     }
00492 
00493     return 1;
00494 }
00495 
00496 
00497 int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
00498 {
00499         word32     i;
00500         wc_Memory* pt;
00501 
00502         XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
00503 
00504         stats->totalAlloc = heap->alloc;
00505         stats->totalFr    = heap->frAlc;
00506         stats->curAlloc   = stats->totalAlloc - stats->totalFr;
00507         stats->maxHa      = heap->maxHa;
00508         stats->maxIO      = heap->maxIO;
00509         for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00510             stats->blockSz[i] = heap->sizeList[i];
00511             for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
00512                 stats->avaBlock[i] += 1;
00513             }
00514         }
00515 
00516         for (pt = heap->io; pt != NULL; pt = pt->next) {
00517             stats->avaIO++;
00518         }
00519 
00520         stats->flag       = heap->flag; /* flag used */
00521 
00522     return 1;
00523 }
00524 
00525 
00526 #ifdef WOLFSSL_DEBUG_MEMORY
00527 void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
00528 #else
00529 void* wolfSSL_Malloc(size_t size, void* heap, int type)
00530 #endif
00531 {
00532     void* res = 0;
00533     wc_Memory* pt = NULL;
00534     int   i;
00535 
00536     /* check for testing heap hint was set */
00537 #ifdef WOLFSSL_HEAP_TEST
00538     if (heap == (void*)WOLFSSL_HEAP_TEST) {
00539         return malloc(size);
00540     }
00541 #endif
00542 
00543     /* if no heap hint then use dynamic memory*/
00544     if (heap == NULL) {
00545         #ifdef WOLFSSL_HEAP_TEST
00546             /* allow using malloc for creating ctx and method */
00547             if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
00548                                             type == DYNAMIC_TYPE_CERT_MANAGER) {
00549                 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
00550                 res = malloc(size);
00551             }
00552             else {
00553                 WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n");
00554                 res = NULL;
00555             }
00556         #else
00557         #ifndef WOLFSSL_NO_MALLOC
00558             #ifdef FREERTOS
00559                 res = pvPortMalloc(size);
00560             #else
00561                 res = malloc(size);
00562             #endif
00563         #else
00564             WOLFSSL_MSG("No heap hint found to use and no malloc");
00565             #ifdef WOLFSSL_DEBUG_MEMORY
00566             printf("ERROR: at %s:%d\n", func, line);
00567             #endif
00568         #endif /* WOLFSSL_NO_MALLOC */
00569         #endif /* WOLFSSL_HEAP_TEST */
00570     }
00571     else {
00572         WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00573         WOLFSSL_HEAP*      mem  = hint->memory;
00574 
00575         if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00576             WOLFSSL_MSG("Bad memory_mutex lock");
00577             return NULL;
00578         }
00579 
00580         /* case of using fixed IO buffers */
00581         if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
00582                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00583                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00584             if (type == DYNAMIC_TYPE_OUT_BUFFER) {
00585                 pt = hint->outBuf;
00586             }
00587             if (type == DYNAMIC_TYPE_IN_BUFFER) {
00588                 pt = hint->inBuf;
00589             }
00590         }
00591         else {
00592             /* check if using IO pool flag */
00593             if (mem->flag & WOLFMEM_IO_POOL &&
00594                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00595                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00596                 if (mem->io != NULL) {
00597                     pt      = mem->io;
00598                     mem->io = pt->next;
00599                 }
00600             }
00601 
00602             /* general static memory */
00603             if (pt == NULL) {
00604                 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00605                     if ((word32)size < mem->sizeList[i]) {
00606                         if (mem->ava[i] != NULL) {
00607                             pt = mem->ava[i];
00608                             mem->ava[i] = pt->next;
00609                             break;
00610                         }
00611                     }
00612                 }
00613             }
00614         }
00615 
00616         if (pt != NULL) {
00617             mem->inUse += pt->sz;
00618             mem->alloc += 1;
00619             res = pt->buffer;
00620 
00621         #ifdef WOLFSSL_DEBUG_MEMORY
00622             printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
00623         #endif
00624 
00625             /* keep track of connection statistics if flag is set */
00626             if (mem->flag & WOLFMEM_TRACK_STATS) {
00627                 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
00628                 if (stats != NULL) {
00629                     stats->curMem += pt->sz;
00630                     if (stats->peakMem < stats->curMem) {
00631                         stats->peakMem = stats->curMem;
00632                     }
00633                     stats->curAlloc++;
00634                     if (stats->peakAlloc < stats->curAlloc) {
00635                         stats->peakAlloc = stats->curAlloc;
00636                     }
00637                     stats->totalAlloc++;
00638                 }
00639             }
00640         }
00641         else {
00642             WOLFSSL_MSG("ERROR ran out of static memory");
00643             #ifdef WOLFSSL_DEBUG_MEMORY
00644             printf("Looking for %lu bytes at %s:%d\n", size, func, line);
00645             #endif
00646         }
00647 
00648         wc_UnLockMutex(&(mem->memory_mutex));
00649     }
00650 
00651     #ifdef WOLFSSL_MALLOC_CHECK
00652         if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
00653             WOLFSSL_MSG("ERROR memory is not alligned");
00654             res = NULL;
00655         }
00656     #endif
00657 
00658 
00659     (void)i;
00660     (void)pt;
00661     (void)type;
00662 
00663     return res;
00664 }
00665 
00666 
00667 #ifdef WOLFSSL_DEBUG_MEMORY
00668 void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
00669 #else
00670 void wolfSSL_Free(void *ptr, void* heap, int type)
00671 #endif
00672 {
00673     int i;
00674     wc_Memory* pt;
00675 
00676     if (ptr) {
00677         /* check for testing heap hint was set */
00678     #ifdef WOLFSSL_HEAP_TEST
00679         if (heap == (void*)WOLFSSL_HEAP_TEST) {
00680             return free(ptr);
00681         }
00682     #endif
00683 
00684         if (heap == NULL) {
00685         #ifdef WOLFSSL_HEAP_TEST
00686             /* allow using malloc for creating ctx and method */
00687             if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
00688                                             type == DYNAMIC_TYPE_CERT_MANAGER) {
00689                 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
00690             }
00691             else {
00692                 WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n");
00693             }
00694         #endif
00695         #ifndef WOLFSSL_NO_MALLOC
00696             #ifdef FREERTOS
00697                 vPortFree(ptr);
00698             #else
00699                 free(ptr);
00700             #endif
00701         #else
00702             WOLFSSL_MSG("Error trying to call free when turned off");
00703         #endif /* WOLFSSL_NO_MALLOC */
00704         }
00705         else {
00706             WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00707             WOLFSSL_HEAP*      mem  = hint->memory;
00708             word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
00709 
00710             /* get memory struct and add it to available list */
00711             pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
00712             if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00713                 WOLFSSL_MSG("Bad memory_mutex lock");
00714                 return;
00715             }
00716 
00717             /* case of using fixed IO buffers */
00718             if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
00719                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00720                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00721                 /* fixed IO pools are free'd at the end of SSL lifetime
00722                    using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
00723             }
00724             else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
00725                                              (type == DYNAMIC_TYPE_OUT_BUFFER ||
00726                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00727                 pt->next = mem->io;
00728                 mem->io  = pt;
00729             }
00730             else { /* general memory free */
00731                 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00732                     if (pt->sz == mem->sizeList[i]) {
00733                         pt->next = mem->ava[i];
00734                         mem->ava[i] = pt;
00735                         break;
00736                     }
00737                 }
00738             }
00739             mem->inUse -= pt->sz;
00740             mem->frAlc += 1;
00741 
00742         #ifdef WOLFSSL_DEBUG_MEMORY
00743             printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
00744         #endif
00745 
00746             /* keep track of connection statistics if flag is set */
00747             if (mem->flag & WOLFMEM_TRACK_STATS) {
00748                 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
00749                 if (stats != NULL) {
00750                     /* avoid under flow */
00751                     if (stats->curMem > pt->sz) {
00752                         stats->curMem -= pt->sz;
00753                     }
00754                     else {
00755                         stats->curMem = 0;
00756                     }
00757 
00758                     if (stats->curAlloc > 0) {
00759                         stats->curAlloc--;
00760                     }
00761                     stats->totalFr++;
00762                 }
00763             }
00764             wc_UnLockMutex(&(mem->memory_mutex));
00765         }
00766     }
00767 
00768     (void)i;
00769     (void)pt;
00770     (void)type;
00771 }
00772 
00773 #ifdef WOLFSSL_DEBUG_MEMORY
00774 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
00775 #else
00776 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
00777 #endif
00778 {
00779     void* res = 0;
00780     wc_Memory* pt = NULL;
00781     word32 prvSz;
00782     int    i;
00783 
00784     /* check for testing heap hint was set */
00785 #ifdef WOLFSSL_HEAP_TEST
00786     if (heap == (void*)WOLFSSL_HEAP_TEST) {
00787         return realloc(ptr, size);
00788     }
00789 #endif
00790 
00791     if (heap == NULL) {
00792         #ifdef WOLFSSL_HEAP_TEST
00793             WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n");
00794         #endif
00795         #ifndef WOLFSSL_NO_MALLOC
00796             res = realloc(ptr, size);
00797         #else
00798             WOLFSSL_MSG("NO heap found to use for realloc");
00799         #endif /* WOLFSSL_NO_MALLOC */
00800     }
00801     else {
00802         WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
00803         WOLFSSL_HEAP*      mem  = hint->memory;
00804         word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
00805 
00806         if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00807             WOLFSSL_MSG("Bad memory_mutex lock");
00808             return NULL;
00809         }
00810 
00811         /* case of using fixed IO buffers or IO pool */
00812         if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
00813                                           && (type == DYNAMIC_TYPE_OUT_BUFFER ||
00814                                               type == DYNAMIC_TYPE_IN_BUFFER)) {
00815             /* no realloc, is fixed size */
00816             pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
00817             if (pt->sz < size) {
00818                 WOLFSSL_MSG("Error IO memory was not large enough");
00819                 res = NULL; /* return NULL in error case */
00820             }
00821             res = pt->buffer;
00822         }
00823         else {
00824         /* general memory */
00825             for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
00826                 if ((word32)size < mem->sizeList[i]) {
00827                     if (mem->ava[i] != NULL) {
00828                         pt = mem->ava[i];
00829                         mem->ava[i] = pt->next;
00830                         break;
00831                     }
00832                 }
00833             }
00834 
00835             if (pt != NULL && res == NULL) {
00836                 res = pt->buffer;
00837 
00838                 /* copy over original information and free ptr */
00839                 prvSz = ((wc_Memory*)((byte*)ptr - padSz -
00840                                                sizeof(wc_Memory)))->sz;
00841                 prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
00842                 XMEMCPY(pt->buffer, ptr, prvSz);
00843                 mem->inUse += pt->sz;
00844                 mem->alloc += 1;
00845 
00846                 /* free memory that was previously being used */
00847                 wc_UnLockMutex(&(mem->memory_mutex));
00848                 wolfSSL_Free(ptr, heap, type
00849             #ifdef WOLFSSL_DEBUG_MEMORY
00850                     , func, line
00851             #endif
00852                 );
00853                 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
00854                     WOLFSSL_MSG("Bad memory_mutex lock");
00855                     return NULL;
00856                 }
00857             }
00858         }
00859         wc_UnLockMutex(&(mem->memory_mutex));
00860     }
00861 
00862     #ifdef WOLFSSL_MALLOC_CHECK
00863         if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
00864             WOLFSSL_MSG("ERROR memory is not alligned");
00865             res = NULL;
00866         }
00867     #endif
00868 
00869     (void)i;
00870     (void)pt;
00871     (void)type;
00872 
00873     return res;
00874 }
00875 #endif /* WOLFSSL_STATIC_MEMORY */
00876 
00877 #endif /* USE_WOLFSSL_MEMORY */
00878 
00879 
00880 #ifdef HAVE_IO_POOL
00881 
00882 /* Example for user io pool, shared build may need definitions in lib proper */
00883 
00884 #include <wolfssl/wolfcrypt/types.h>
00885 #include <stdlib.h>
00886 
00887 #ifndef HAVE_THREAD_LS
00888     #error "Oops, simple I/O pool example needs thread local storage"
00889 #endif
00890 
00891 
00892 /* allow simple per thread in and out pools */
00893 /* use 17k size since max record size is 16k plus overhead */
00894 static THREAD_LS_T byte pool_in[17*1024];
00895 static THREAD_LS_T byte pool_out[17*1024];
00896 
00897 
00898 void* XMALLOC(size_t n, void* heap, int type)
00899 {
00900     (void)heap;
00901 
00902     if (type == DYNAMIC_TYPE_IN_BUFFER) {
00903         if (n < sizeof(pool_in))
00904             return pool_in;
00905         else
00906             return NULL;
00907     }
00908 
00909     if (type == DYNAMIC_TYPE_OUT_BUFFER) {
00910         if (n < sizeof(pool_out))
00911             return pool_out;
00912         else
00913             return NULL;
00914     }
00915 
00916     return malloc(n);
00917 }
00918 
00919 void* XREALLOC(void *p, size_t n, void* heap, int type)
00920 {
00921     (void)heap;
00922 
00923     if (type == DYNAMIC_TYPE_IN_BUFFER) {
00924         if (n < sizeof(pool_in))
00925             return pool_in;
00926         else
00927             return NULL;
00928     }
00929 
00930     if (type == DYNAMIC_TYPE_OUT_BUFFER) {
00931         if (n < sizeof(pool_out))
00932             return pool_out;
00933         else
00934             return NULL;
00935     }
00936 
00937     return realloc(p, n);
00938 }
00939 
00940 void XFREE(void *p, void* heap, int type)
00941 {
00942     (void)heap;
00943 
00944     if (type == DYNAMIC_TYPE_IN_BUFFER)
00945         return;  /* do nothing, static pool */
00946 
00947     if (type == DYNAMIC_TYPE_OUT_BUFFER)
00948         return;  /* do nothing, static pool */
00949 
00950     free(p);
00951 }
00952 
00953 #endif /* HAVE_IO_POOL */
00954 
00955