From 18d80864b93a72e5b92ad34b76b088e512412160 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 29 May 2024 14:11:03 -0600 Subject: [PATCH] add lean static memory build --- wolfcrypt/src/memory.c | 149 +++++++++++++++++++++++++++++------ wolfssl/wolfcrypt/memory.h | 25 ++++++ wolfssl/wolfcrypt/settings.h | 10 +-- 3 files changed, 155 insertions(+), 29 deletions(-) diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 7fd8a019a..6e834d958 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -514,20 +514,39 @@ void* wolfSSL_Realloc(void *ptr, size_t size) struct wc_Memory { byte* buffer; struct wc_Memory* next; +#ifdef WOLFSSL_LEAN_STATIC_MEMORY + /* lean static memory is assumed to be under 65k */ + word16 sz; +#else word32 sz; +#endif +#ifdef WOLFSSL_DEBUG_MEMORY + word16 szUsed; +#endif }; +#ifdef WOLFSSL_DEBUG_MEMORY_CALLBACK +static DebugMemoryCb DebugCb = NULL; + +/* Used to set a debug memory callback. Helpful in cases where + * printf is not available. */ +void wolfSSL_SetDebugCallback(DebugMemoryCb in) +{ + DebugCb = in; +} +#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 +561,12 @@ static int wc_create_memory_buckets(byte* buffer, word32 bufSz, mem->buffer = (byte*)pt + padSz + memSz; mem->next = NULL; + #ifdef WOLFSSL_DEBUG_MEMORY_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 +593,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"); @@ -631,15 +656,25 @@ static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz, const unsigned int* sizeList, const unsigned int* distList) { + word16 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 +686,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 +739,7 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, return MEMORY_E; } +#ifndef WOLFSSL_LEAN_STATIC_MEMORY /* determine what max applies too */ if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { heap->maxIO = maxSz; @@ -711,8 +747,8 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, else { /* general memory used in handshakes */ heap->maxHa = maxSz; } - heap->flag |= flag; +#endif *pHint = hint; return 0; @@ -721,8 +757,13 @@ int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, 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 +783,7 @@ void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap) } } - +#ifndef WOLFSSL_LEAN_STATIC_MEMORY /* 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 +823,7 @@ int wolfSSL_StaticBufferSz_ex(unsigned int listSz, ava--; } +#ifndef WOLFSSL_LEAN_STATIC_MEMORY /* 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 +832,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 +941,7 @@ int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) return 1; } +#endif /* !WOLFSSL_LEAN_STATIC_MEMORY */ /* global heap hint to fall back on when no heap hint is passed to @@ -987,11 +1032,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_LEAN_STATIC_MEMORY /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1003,7 +1051,10 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - else { + else + #endif + { + #ifndef WOLFSSL_LEANPSK /* check if using IO pool flag */ if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1013,6 +1064,7 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) mem->io = pt->next; } } + #endif /* general static memory */ if (pt == NULL) { @@ -1035,14 +1087,21 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } if (pt != NULL) { - mem->inUse += pt->sz; + #ifndef WOLFSSL_LEAN_STATIC_MEMORY 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_DEBUG_MEMORY_CALLBACK + if (DebugCb) { + DebugCb(size, pt->sz, WOLFSSL_DEBUG_MEMORY_ALLOC, type); + } + #endif + #ifndef WOLFSSL_LEAN_STATIC_MEMORY /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -1058,16 +1117,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_DEBUG_MEMORY_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 +1215,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_LEAN_STATIC_MEMORY /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1166,22 +1236,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_DEBUG_MEMORY_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_LEAN_STATIC_MEMORY 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_LEAN_STATIC_MEMORY /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -1200,7 +1286,10 @@ void wolfSSL_Free(void *ptr, void* heap, int type) stats->totalFr++; } } + #endif + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } } @@ -1209,6 +1298,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,11 +1346,12 @@ 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 /* case of using fixed IO buffers or IO pool */ if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) @@ -1287,30 +1378,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_LEAN_STATIC_MEMORY 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 +1428,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/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index a901a64c3..a91484f8b 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_LEAN_STATIC_MEMORY wc_Memory* io; /* list of buffers to use for IO */ + #endif + + #ifdef WOLFSSL_LEAN_STATIC_MEMORY + 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_LEAN_STATIC_MEMORY 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_LEAN_STATIC_MEMORY 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_DEBUG_MEMORY_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..3be750bb8 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,7 +3257,8 @@ 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)) + (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) #endif