wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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