diff --git a/configure.ac b/configure.ac index ae84cf659..dec2b1ef4 100644 --- a/configure.ac +++ b/configure.ac @@ -8070,6 +8070,27 @@ AC_ARG_ENABLE([staticmemory], [ ENABLED_STATICMEMORY=no ] ) +for v in `echo $ENABLED_STATICMEMORY | tr "," " "` +do + case $v in + yes) + ;; + no) + ;; + small|lean) + ENABLED_STATICMEMORY=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY_LEAN" + ;; + debug) + ENABLED_STATICMEMORY=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK" + ;; + *) + AC_MSG_ERROR([Invalid choice for staticmemory.]) + break;; + esac +done + if test "x$ENABLED_STATICMEMORY" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY" diff --git a/examples/client/client.c b/examples/client/client.c index f1ab9ea13..efad24a20 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1865,6 +1865,39 @@ static int client_srtp_test(WOLFSSL *ssl, func_args *args) } #endif /* WOLFSSL_SRTP */ +#if defined(WOLFSSL_STATIC_MEMORY) && \ + defined(WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK) +static void ExampleDebugMemoryCb(size_t sz, int bucketSz, byte st, int type) { + switch (st) { + case WOLFSSL_DEBUG_MEMORY_ALLOC: + if (type == DYNAMIC_TYPE_IN_BUFFER) { + printf("IN BUFFER: "); + } + + if (type == DYNAMIC_TYPE_OUT_BUFFER) { + printf("OUT BUFFER: "); + } + + printf("Alloc'd %d bytes using bucket size %d\n", (int)sz, + bucketSz); + break; + + case WOLFSSL_DEBUG_MEMORY_FAIL: + printf("Failed when trying to allocate %d bytes\n", (int)sz); + break; + + case WOLFSSL_DEBUG_MEMORY_FREE: + printf("Free'ing : %d\n", (int)sz); + break; + + case WOLFSSL_DEBUG_MEMORY_INIT: + printf("Creating memory bucket of size : %d\n", bucketSz); + break; + } +} +#endif + + THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { @@ -2096,10 +2129,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) byte memory[80000]; #endif byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */ + #if !defined(WOLFSSL_STATIC_MEMORY_LEAN) WOLFSSL_MEM_CONN_STATS ssl_stats; - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) WOLFSSL_MEM_STATS mem_stats; #endif + #endif WOLFSSL_HEAP_HINT *heap = NULL; #endif @@ -3026,7 +3061,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_STATIC_MEMORY - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) /* print off helper buffer sizes for use with static memory * printing to stderr in case of debug mode turned on */ LOG_ERROR("static memory management size = %d\n", @@ -3043,6 +3078,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("unable to load static memory"); } +#if defined(WOLFSSL_STATIC_MEMORY) && \ + defined(WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK) + wolfSSL_SetDebugMemoryCb(ExampleDebugMemoryCb); +#endif ctx = wolfSSL_CTX_new_ex(method(heap), heap); if (ctx == NULL) err_sys("unable to get ctx"); @@ -3584,7 +3623,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif -#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) && \ + !defined(WOLFSSL_STATIC_MEMORY_LEAN) LOG_ERROR("Before creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys("ctx not using static memory"); @@ -3682,7 +3722,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif -#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) && \ + !defined(WOLFSSL_STATIC_MEMORY_LEAN) LOG_ERROR("After creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys("ctx not using static memory"); @@ -4390,7 +4431,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif /* display collected statistics */ -#ifdef WOLFSSL_STATIC_MEMORY +#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) err_sys("static memory was not used with ssl"); @@ -4617,7 +4658,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_shutdown(sslResume); /* bidirectional shutdown */ /* display collected statistics */ - #ifdef WOLFSSL_STATIC_MEMORY + #if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) if (wolfSSL_is_static_memory(sslResume, &ssl_stats) != 1) err_sys("static memory was not used with ssl"); diff --git a/examples/server/server.c b/examples/server/server.c index 7d24b3f2c..cca853a14 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1601,10 +1601,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) byte memory[80000]; #endif byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */ + #if !defined(WOLFSSL_STATIC_MEMORY_LEAN) WOLFSSL_MEM_CONN_STATS ssl_stats; - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) WOLFSSL_MEM_STATS mem_stats; #endif + #endif #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) int onlyKeyShare = 0; @@ -2503,7 +2505,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err_sys_ex(runWithErrors, "unable to get method"); #ifdef WOLFSSL_STATIC_MEMORY - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) /* print off helper buffer sizes for use with static memory * printing to stderr in case of debug mode turned on */ LOG_ERROR("static memory management size = %d\n", @@ -2964,7 +2966,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err_sys_ex(runWithErrors, "tcp accept failed"); } } -#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) && \ + !defined(WOLFSSL_STATIC_MEMORY_LEAN) LOG_ERROR("Before creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys_ex(runWithErrors, "ctx not using static memory"); @@ -3053,7 +3056,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } #endif -#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) && \ + !defined(WOLFSSL_STATIC_MEMORY_LEAN) LOG_ERROR("After creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys_ex(runWithErrors, "ctx not using static memory"); @@ -3799,7 +3803,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } /* display collected statistics */ -#ifdef WOLFSSL_STATIC_MEMORY +#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) err_sys_ex(runWithErrors, "static memory was not used with ssl"); diff --git a/src/internal.c b/src/internal.c index b4f822119..66d8b426b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7241,6 +7241,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap)); + ssl_hint->memory = ctx_hint->memory; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* lock and check IO count / handshake count */ if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); @@ -7268,7 +7270,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } ctx_hint->memory->curIO++; ctx_hint->memory->curHa++; - ssl_hint->memory = ctx_hint->memory; ssl_hint->haFlag = 1; wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); @@ -7304,6 +7305,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); } + #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ #ifdef WOLFSSL_HEAP_TEST } #endif @@ -8382,14 +8384,17 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* avoid dereferencing a test value */ if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { #endif + void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; WOLFSSL_HEAP* ctx_heap; - void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); } + #endif ctx_heap->curIO--; if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) { WOLFSSL_MSG("Error freeing fixed output buffer"); @@ -8397,15 +8402,20 @@ void SSL_ResourceFree(WOLFSSL* ssl) if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) { WOLFSSL_MSG("Error freeing fixed output buffer"); } - if (ssl_hint->haFlag && ctx_heap->curHa > 0) { /* check if handshake count has been decreased*/ + + /* check if handshake count has been decreased*/ + if (ssl_hint->haFlag && ctx_heap->curHa > 0) { ctx_heap->curHa--; } + #ifndef SINGLE_THREADED wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif /* check if tracking stats */ if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); } + #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); #ifdef WOLFSSL_HEAP_TEST } @@ -8673,14 +8683,20 @@ void FreeHandshakeResources(WOLFSSL* ssl) WOLFSSL_HEAP* ctx_heap; ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN if (ctx_heap->curHa > 0) { ctx_heap->curHa--; } ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */ + #endif + #ifndef SINGLE_THREADED wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif #ifdef WOLFSSL_HEAP_TEST } #endif diff --git a/src/ssl.c b/src/ssl.c index 25b1d450f..5fd3364b9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2573,6 +2573,7 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) } WOLFSSL_ENTER("wolfSSL_is_static_memory"); +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */ if (mem_stats != NULL && ssl->heap != NULL) { WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); @@ -2581,7 +2582,9 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS)); } } +#endif + (void)mem_stats; return (ssl->heap) ? 1 : 0; } @@ -2593,6 +2596,7 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) } WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory"); +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* fill out statistics if wanted */ if (mem_stats != NULL && ctx->heap != NULL) { WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory; @@ -2600,7 +2604,9 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) return MEMORY_E; } } +#endif + (void)mem_stats; return (ctx->heap) ? 1 : 0; } diff --git a/tests/api.c b/tests/api.c index 785924a16..bc73a3515 100644 --- a/tests/api.c +++ b/tests/api.c @@ -66534,7 +66534,7 @@ static int test_wolfSSL_CTX_StaticMemory_SSL(WOLFSSL_CTX* ctx) ExpectNull((ssl3 = wolfSSL_new(ctx))); if (wolfSSL_is_static_memory(ssl1, &ssl_stats) == 1) { - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) wolfSSL_PrintStatsConn(&ssl_stats); #endif (void)ssl_stats; @@ -66542,7 +66542,7 @@ static int test_wolfSSL_CTX_StaticMemory_SSL(WOLFSSL_CTX* ctx) /* display collected statistics */ if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) == 1) { - #ifdef DEBUG_WOLFSSL + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) wolfSSL_PrintStats(&mem_stats); #endif (void)mem_stats; diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 7fd8a019a..d9958a9e3 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -38,6 +38,16 @@ Possible memory options: * NO_WOLFSSL_MEMORY: Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY. * WOLFSSL_STATIC_MEMORY: Turns on the use of static memory buffers and functions. This allows for using static memory instead of dynamic. + * WOLFSSL_STATIC_MEMORY_LEAN: Requires WOLFSSL_STATIC_MEMORY be defined. + * Uses smaller type sizes for structs + * requiring that memory pool sizes be less + * then 65k and limits features available like + * IO buffers to reduce footprint size. + * WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK: + * Enables option to register a debugging + * callback function, useful for + * WOLFSSL_STATIC_MEMORY builds where XMALLOC + * and XFREE are not user defined. * WOLFSSL_STATIC_ALIGN: Define defaults to 16 to indicate static memory alignment. * HAVE_IO_POOL: Enables use of static thread safe memory pool for input/output buffers. * XMALLOC_OVERRIDE: Allows override of the XMALLOC, XFREE and XREALLOC macros. @@ -514,20 +524,39 @@ void* wolfSSL_Realloc(void *ptr, size_t size) struct wc_Memory { byte* buffer; struct wc_Memory* next; +#ifdef WOLFSSL_STATIC_MEMORY_LEAN + /* lean static memory is assumed to be under 65k */ + word16 sz; +#else word32 sz; +#endif +#ifdef WOLFSSL_DEBUG_MEMORY + word16 szUsed; +#endif }; +#ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK +static DebugMemoryCb DebugCb = NULL; + +/* Used to set a debug memory callback. Helpful in cases where + * printf is not available. */ +void wolfSSL_SetDebugMemoryCb(DebugMemoryCb cb) +{ + DebugCb = cb; +} +#endif + /* returns amount of memory used on success. On error returns negative value wc_Memory** list is the list that new buckets are prepended to */ static int wc_create_memory_buckets(byte* buffer, word32 bufSz, - word32 buckSz, word32 buckNum, wc_Memory** list) { - word32 i; + word32 buckSz, byte buckNum, wc_Memory** list) { byte* pt = buffer; int ret = 0; - word32 memSz = (word32)sizeof(wc_Memory); - word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + byte memSz = (byte)sizeof(wc_Memory); + word16 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + word16 i; /* if not enough space available for bucket size then do not try */ if (buckSz + memSz + padSz > bufSz) { @@ -542,6 +571,12 @@ static int wc_create_memory_buckets(byte* buffer, word32 bufSz, mem->buffer = (byte*)pt + padSz + memSz; mem->next = NULL; + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(buckSz, buckSz, WOLFSSL_DEBUG_MEMORY_INIT, 0); + } + #endif + /* add the newly created struct to front of list */ if (*list == NULL) { *list = mem; @@ -568,8 +603,8 @@ static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, word32 ava = sz; byte* pt = buffer; int ret = 0; - word32 memSz = (word32)sizeof(wc_Memory); - word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + byte memSz = (word32)sizeof(wc_Memory); + byte padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); WOLFSSL_ENTER("wc_partition_static_memory"); @@ -585,7 +620,8 @@ static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, #endif /* divide into chunks of memory and add them to available list */ - while (ava >= (heap->sizeList[0] + padSz + memSz)) { + while (ava >= (word32)(heap->sizeList[0] + padSz + memSz)) { + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* creating only IO buffers from memory passed in, max TLS is 16k */ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { if ((ret = wc_create_memory_buckets(pt, ava, @@ -604,11 +640,13 @@ static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, pt += ret; ava -= ret; } - else { + else + #endif + { int i; /* start at largest and move to smaller buckets */ for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { - if ((heap->sizeList[i] + padSz + memSz) <= ava) { + if ((word32)(heap->sizeList[i] + padSz + memSz) <= ava) { if ((ret = wc_create_memory_buckets(pt, ava, heap->sizeList[i], heap->distList[i], &(heap->ava[i]))) < 0) { @@ -625,21 +663,32 @@ static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, } } + (void)flag; return 1; } static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz, const unsigned int* sizeList, const unsigned int* distList) { + unsigned int i; + XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); - XMEMCPY(heap->sizeList, sizeList, listSz * sizeof(sizeList[0])); - XMEMCPY(heap->distList, distList, listSz * sizeof(distList[0])); + /* avoid XMEMCPY for LEAN static memory build */ + for (i = 0; i < listSz; i++) { + heap->sizeList[i] = sizeList[i]; + } + for (i = 0; i < listSz; i++) { + heap->distList[i] = distList[i]; + } + +#ifndef SINGLE_THREADED if (wc_InitMutex(&(heap->memory_mutex)) != 0) { WOLFSSL_MSG("Error creating heap memory mutex"); return BAD_MUTEX_E; } +#endif return 0; } @@ -651,7 +700,7 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, { WOLFSSL_HEAP* heap = NULL; WOLFSSL_HEAP_HINT* hint = NULL; - word32 idx = 0; + word16 idx = 0; int ret; WOLFSSL_ENTER("wc_LoadStaticMemory_ex"); @@ -704,6 +753,7 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, return MEMORY_E; } +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* determine what max applies too */ if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { heap->maxIO = maxSz; @@ -711,18 +761,24 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, else { /* general memory used in handshakes */ heap->maxHa = maxSz; } - heap->flag |= flag; +#endif *pHint = hint; + (void)maxSz; return 0; } int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, unsigned char* buf, unsigned int sz, int flag, int maxSz) { +#ifdef WOLFSSL_LEAN_STATIC_PSK + word16 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + byte distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; +#else word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; +#endif int ret = 0; WOLFSSL_ENTER("wc_LoadStaticMemory"); @@ -742,7 +798,7 @@ void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap) } } - +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* returns the size of management memory needed for each bucket. * This is memory that is used to keep track of and align memory buckets. */ int wolfSSL_MemoryPaddingSz(void) @@ -782,6 +838,7 @@ int wolfSSL_StaticBufferSz_ex(unsigned int listSz, ava--; } +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* creating only IO buffers from memory passed in, max TLS is 16k */ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { @@ -790,7 +847,9 @@ int wolfSSL_StaticBufferSz_ex(unsigned int listSz, ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); } - else { + else +#endif + { int i, k; if (ava < (sizeList[0] + padSz + memSz)) { @@ -897,6 +956,7 @@ int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) return 1; } +#endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ /* global heap hint to fall back on when no heap hint is passed to @@ -987,11 +1047,14 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } mem = hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1003,7 +1066,10 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - else { + else + #endif + { + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* check if using IO pool flag */ if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1013,6 +1079,7 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) mem->io = pt->next; } } + #endif /* general static memory */ if (pt == NULL) { @@ -1035,14 +1102,21 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } if (pt != NULL) { - mem->inUse += pt->sz; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->alloc += 1; + #endif res = pt->buffer; #ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + pt->szUsed = size; + fprintf(stderr, "Alloc: %p -> %lu at %s:%d\n", pt->buffer, size, func, line); #endif - + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(size, pt->sz, WOLFSSL_DEBUG_MEMORY_ALLOC, type); + } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -1058,16 +1132,24 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) stats->totalAlloc++; } } + #endif } else { WOLFSSL_MSG("ERROR ran out of static memory"); + res = NULL; #ifdef WOLFSSL_DEBUG_MEMORY fprintf(stderr, "Looking for %lu bytes at %s:%d\n", (unsigned long) size, func, line); #endif + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(size, 0, WOLFSSL_DEBUG_MEMORY_FAIL, type); + } + #endif } - + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } #ifdef WOLFSSL_MALLOC_CHECK @@ -1148,11 +1230,14 @@ void wolfSSL_Free(void *ptr, void* heap, int type) /* get memory struct and add it to available list */ pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz); + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1166,22 +1251,38 @@ void wolfSSL_Free(void *ptr, void* heap, int type) pt->next = mem->io; mem->io = pt; } - else { /* general memory free */ + else + #endif + { /* general memory free */ for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if (pt->sz == mem->sizeList[i]) { pt->next = mem->ava[i]; mem->ava[i] = pt; + + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + #ifdef WOLFSSL_DEBUG_MEMORY + DebugCb(pt->szUsed, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type); + #else + DebugCb(pt->sz, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type); + #endif + } + #endif break; } } } + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->inUse -= pt->sz; mem->frAlc += 1; - - #ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); #endif + #ifdef WOLFSSL_DEBUG_MEMORY + fprintf (stderr, "Free: %p -> %u at %s:%d\n", pt->buffer, + pt->szUsed, func, line); + #endif + + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -1200,7 +1301,10 @@ void wolfSSL_Free(void *ptr, void* heap, int type) stats->totalFr++; } } + #endif + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } } @@ -1209,6 +1313,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) (void)type; } +#ifndef WOLFSSL_NO_REALLOC #ifdef WOLFSSL_DEBUG_MEMORY void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line) #else @@ -1256,12 +1361,14 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) return wolfSSL_Malloc(size, heap, type); #endif } - + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers or IO pool */ if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1274,7 +1381,9 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } res = pt->buffer; } - else { + else + #endif + { /* general memory */ for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if ((word32)size <= mem->sizeList[i]) { @@ -1287,30 +1396,40 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } if (pt != NULL && res == NULL) { + word32 prvSz; + res = pt->buffer; /* copy over original information and free ptr */ - word32 prvSz = ((wc_Memory*)((byte*)ptr - padSz - + prvSz = ((wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory)))->sz; prvSz = (prvSz > pt->sz)? pt->sz: prvSz; XMEMCPY(pt->buffer, ptr, prvSz); + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->inUse += pt->sz; mem->alloc += 1; + #endif /* free memory that was previously being used */ + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif wolfSSL_Free(ptr, heap, type #ifdef WOLFSSL_DEBUG_MEMORY , func, line #endif ); + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif } } + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } #ifdef WOLFSSL_MALLOC_CHECK @@ -1327,7 +1446,7 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) return res; } #endif /* WOLFSSL_STATIC_MEMORY */ - +#endif /* WOLFSSL_NO_REALLOC */ #endif /* USE_WOLFSSL_MEMORY */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 604e2c627..fec1918bb 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -17406,6 +17406,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void) } } +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* check that padding size returned is possible */ if (wolfSSL_MemoryPaddingSz() < WOLFSSL_STATIC_ALIGN) { return WC_TEST_RET_ENC_NC; /* no room for wc_Memory struct */ @@ -17470,7 +17471,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void) return WC_TEST_RET_ENC_NC; /* should round to 0 since struct + bucket will not fit */ } +#endif + (void)pad; (void)dist; /* avoid static analysis warning of variable not used */ #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index bad365fc9..4dd6320e7 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -3102,7 +3102,7 @@ static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl) #endif /* ATOMIC_USER */ -#ifdef WOLFSSL_STATIC_MEMORY +#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) static WC_INLINE int wolfSSL_PrintStats(WOLFSSL_MEM_STATS* stats) { word16 i; diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index a901a64c3..31b6a28f5 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -214,7 +214,14 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */ typedef struct WOLFSSL_HEAP { wc_Memory* ava[WOLFMEM_MAX_BUCKETS]; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN wc_Memory* io; /* list of buffers to use for IO */ + #endif + + #ifdef WOLFSSL_STATIC_MEMORY_LEAN + word16 sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */ + byte distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ + #else word32 maxHa; /* max concurrent handshakes */ word32 curHa; word32 maxIO; /* max concurrent IO connections */ @@ -223,10 +230,16 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, word32 distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ word32 inUse; /* amount of memory currently in use */ word32 ioUse; + #endif + + #ifndef WOLFSSL_STATIC_MEMORY_LEAN word32 alloc; /* total number of allocs */ word32 frAlc; /* total number of frees */ int flag; + #endif + #ifndef SINGLE_THREADED wolfSSL_Mutex memory_mutex; + #endif } WOLFSSL_HEAP; /* structure passed into XMALLOC as heap hint @@ -235,9 +248,11 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, typedef struct WOLFSSL_HEAP_HINT { WOLFSSL_HEAP* memory; WOLFSSL_MEM_CONN_STATS* stats; /* hold individual connection stats */ + #ifndef WOLFSSL_STATIC_MEMORY_LEAN wc_Memory* outBuf; /* set if using fixed io buffers */ wc_Memory* inBuf; byte haFlag; /* flag used for checking handshake count */ + #endif } WOLFSSL_HEAP_HINT; WOLFSSL_API void* wolfSSL_SetGlobalHeapHint(void* heap); @@ -246,6 +261,16 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, unsigned int listSz, const unsigned int *sizeList, const unsigned int *distList, unsigned char* buf, unsigned int sz, int flag, int max); +#ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + #define WOLFSSL_DEBUG_MEMORY_ALLOC 0 + #define WOLFSSL_DEBUG_MEMORY_FAIL 1 + #define WOLFSSL_DEBUG_MEMORY_FREE 2 + #define WOLFSSL_DEBUG_MEMORY_INIT 3 + + + typedef void (*DebugMemoryCb)(size_t sz, int bucketSz, byte st, int type); + WOLFSSL_API void wolfSSL_SetDebugMemoryCb(DebugMemoryCb cb); +#endif WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, unsigned char* buf, unsigned int sz, int flag, int max); WOLFSSL_API void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index ee25c7e8c..146e5c594 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1036,7 +1036,7 @@ extern void uITRON4_free(void *p) ; #if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER) && \ - !defined(NO_WOLFSSL_MEMORY) + !defined(NO_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) #include #define XMALLOC(s, h, type) ((void)(h), (void)(type), malloc((s))) #define XFREE(p, h, type) ((void)(h), (void)(type), free((p))) @@ -1327,8 +1327,10 @@ extern void uITRON4_free(void *p) ; /* Copy data out of flash memory and into SRAM */ #define XMEMCPY_P(pdest, psrc, size) memcpy_P((pdest), (psrc), (size)) #else +#ifndef FLASH_QUALIFIER #define FLASH_QUALIFIER #endif +#endif #ifdef FREESCALE_MQX_5_0 /* use normal Freescale MQX port, but with minor changes for 5.0 */ @@ -2815,9 +2817,6 @@ extern void uITRON4_free(void *p) ; !defined(WOLFSSL_SP_MATH) && !defined(NO_BIG_INT) #error The static memory option is only supported for fast math or SP Math #endif - #ifdef WOLFSSL_SMALL_STACK - #error static memory does not support small stack please undefine - #endif #endif /* WOLFSSL_STATIC_MEMORY */ #ifdef HAVE_AES_KEYWRAP @@ -3258,8 +3257,10 @@ extern void uITRON4_free(void *p) ; /* Do not allow using small stack with no malloc */ #if defined(WOLFSSL_NO_MALLOC) && \ - (defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) - #error Small stack cannot be used with no malloc (WOLFSSL_NO_MALLOC) + (defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #error Small stack cannot be used with no malloc (WOLFSSL_NO_MALLOC) and \ + without staticmemory (WOLFSSL_STATIC_MEMORY) #endif /* If malloc is disabled make sure it is also disabled in SP math */