diff --git a/src/ssl.c b/src/ssl.c index 594445014..c2b4f8205 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2572,9 +2572,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method, unsigned char* buf, unsigned int sz, int flag, int maxSz) { - WOLFSSL_HEAP* heap; - WOLFSSL_HEAP_HINT* hint; - word32 idx = 0; + WOLFSSL_HEAP_HINT* hint = NULL; if (ctx == NULL || buf == NULL) { return BAD_FUNC_ARG; @@ -2584,42 +2582,23 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, return BAD_FUNC_ARG; } - if (*ctx == NULL || (*ctx)->heap == NULL) { - if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) { - return BUFFER_E; /* not enough memory for structures */ - } - heap = (WOLFSSL_HEAP*)buf; - idx += sizeof(WOLFSSL_HEAP); - if (wolfSSL_init_memory_heap(heap) != 0) { - return WOLFSSL_FAILURE; - } - hint = (WOLFSSL_HEAP_HINT*)(buf + idx); - idx += sizeof(WOLFSSL_HEAP_HINT); - XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); - hint->memory = heap; + /* If there is a heap already, capture it in hint. */ + if (*ctx && (*ctx)->heap != NULL) { + hint = (*ctx)->heap; + } - if (*ctx && (*ctx)->heap == NULL) { + if (wc_LoadStaticMemory(&hint, buf, sz, flag, maxSz)) { + WOLFSSL_MSG("Error loading static memory"); + return WOLFSSL_FAILURE; + } + + if (*ctx) { + if ((*ctx)->heap == NULL) { (*ctx)->heap = (void*)hint; } } else { -#ifdef WOLFSSL_HEAP_TEST - /* do not load in memory if test has been set */ - if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) { - return WOLFSSL_SUCCESS; - } -#endif - hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap); - heap = hint->memory; - } - - if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) { - WOLFSSL_MSG("Error partitioning memory"); - return WOLFSSL_FAILURE; - } - - /* create ctx if needed */ - if (*ctx == NULL) { + /* create ctx if needed */ *ctx = wolfSSL_CTX_new_ex(method(hint), hint); if (*ctx == NULL) { WOLFSSL_MSG("Error creating ctx"); @@ -2627,19 +2606,6 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, } } - /* determine what max applies too */ - if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - heap->maxIO = maxSz; - } - else { /* general memory used in handshakes */ - heap->maxHa = maxSz; - } - - heap->flag |= flag; - - (void)maxSz; - (void)method; - return WOLFSSL_SUCCESS; } diff --git a/tests/api.c b/tests/api.c index 840ece2c0..aaa155c8a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -672,6 +672,93 @@ static int test_wolfCrypt_Cleanup(void) return EXPECT_RESULT(); } +static int test_wc_LoadStaticMemory_ex(void) +{ + EXPECT_DECLS; +#ifdef WOLFSSL_STATIC_MEMORY + byte staticMemory[440000]; + word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + WOLFSSL_HEAP_HINT* heap; + + /* Pass in zero everything. */ + ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, 0, NULL, NULL, NULL, 0, 0, 0), + BAD_FUNC_ARG); + + /* Set the heap pointer to NULL. */ + ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + + /* Set other pointer values to NULL one at a time. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, NULL, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, NULL, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + NULL, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + /* Set the size of the static buffer to 0. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, 0, + 0, 1), + BUFFER_E); + + /* Set the size of the static buffer to one less than minimum allowed. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, + (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) - 1, + 0, 1), + BUFFER_E); + + /* Set the number of buckets to 1 too many allowed. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_MAX_BUCKETS+1, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + + /* Set the size of the static buffer to exactly the minimum size. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, + (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)), + 0, 1), + 0); + wc_UnloadStaticMemory(heap); + + /* Success case. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + 0); + wc_UnloadStaticMemory(heap); +#endif /* WOLFSSL_STATIC_MEMORY */ + return EXPECT_RESULT(); +} + + /*----------------------------------------------------------------------------* | Platform dependent function test *----------------------------------------------------------------------------*/ @@ -71571,6 +71658,8 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfCrypt_Init), + TEST_DECL(test_wc_LoadStaticMemory_ex), + /* Locking with Compat Mutex */ TEST_DECL(test_wc_SetMutexCb), TEST_DECL(test_wc_LockMutex_ex), diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 4b068ce9c..61fe735b6 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -521,7 +521,7 @@ struct wc_Memory { /* 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 create_memory_buckets(byte* buffer, word32 bufSz, +static int wc_create_memory_buckets(byte* buffer, word32 bufSz, word32 buckSz, word32 buckNum, wc_Memory** list) { word32 i; byte* pt = buffer; @@ -562,19 +562,79 @@ static int create_memory_buckets(byte* buffer, word32 bufSz, return ret; } -int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) +static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, + WOLFSSL_HEAP* heap) { - word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; - word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + word32 ava = sz; + byte* pt = buffer; + int ret = 0; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); - if (heap == NULL) { - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wc_partition_static_memory"); + + /* align pt */ + while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + *pt = 0x00; + pt++; + ava--; } +#ifdef WOLFSSL_DEBUG_MEMORY + fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt); +#endif + + /* divide into chunks of memory and add them to available list */ + while (ava >= (heap->sizeList[0] + padSz + memSz)) { + /* 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, + WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { + WOLFSSL_LEAVE("wc_partition_static_memory", ret); + return ret; + } + + /* check if no more room left for creating IO buffers */ + if (ret == 0) { + break; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + else { + 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 ((ret = wc_create_memory_buckets(pt, ava, + heap->sizeList[i], heap->distList[i], + &(heap->ava[i]))) < 0) { + WOLFSSL_LEAVE("wc_partition_static_memory", ret); + return ret; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + } + } + } + + return 1; +} + +static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz, + const unsigned int* sizeList, const unsigned int* distList) +{ XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); - XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); - XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); + XMEMCPY(heap->sizeList, sizeList, listSz * sizeof(sizeList[0])); + XMEMCPY(heap->distList, distList, listSz * sizeof(distList[0])); if (wc_InitMutex(&(heap->memory_mutex)) != 0) { WOLFSSL_MSG("Error creating heap memory mutex"); @@ -584,19 +644,25 @@ int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) return 0; } -int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, - unsigned char* buf, unsigned int sz, int flag, int maxSz) +int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, + unsigned int listSz, const unsigned int* sizeList, + const unsigned int* distList, unsigned char* buf, + unsigned int sz, int flag, int maxSz) { - int ret; - WOLFSSL_HEAP* heap; - WOLFSSL_HEAP_HINT* hint; + WOLFSSL_HEAP* heap = NULL; + WOLFSSL_HEAP_HINT* hint = NULL; word32 idx = 0; + int ret; - if (pHint == NULL || buf == NULL) { + WOLFSSL_ENTER("wc_LoadStaticMemory_ex"); + + if (pHint == NULL || buf == NULL || listSz > WOLFMEM_MAX_BUCKETS + || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) { + WOLFSSL_MSG("Not enough memory for partition tracking"); return BUFFER_E; /* not enough memory for structures */ } @@ -607,7 +673,7 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, hint = (WOLFSSL_HEAP_HINT*)(buf + idx); idx += sizeof(WOLFSSL_HEAP_HINT); - ret = wolfSSL_init_memory_heap(heap); + ret = wc_init_memory_heap(heap, listSz, sizeList, distList); if (ret != 0) { return ret; } @@ -627,10 +693,10 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, heap = hint->memory; } - ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap); + ret = wc_partition_static_memory(buf + idx, sz - idx, flag, heap); if (ret != 1) { WOLFSSL_MSG("Error partitioning memory"); - return -1; + return MEMORY_E; } /* determine what max applies too */ @@ -644,78 +710,31 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, heap->flag |= flag; *pHint = hint; - (void)maxSz; - return 0; } -int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, - WOLFSSL_HEAP* heap) +int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int maxSz) { - word32 ava = sz; - byte* pt = buffer; - int ret = 0; - word32 memSz = (word32)sizeof(wc_Memory); - word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + int ret = 0; - WOLFSSL_ENTER("wolfSSL_load_static_memory"); + WOLFSSL_ENTER("wc_LoadStaticMemory"); + ret = wc_LoadStaticMemory_ex(pHint, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + buf, sz, flag, maxSz); + WOLFSSL_LEAVE("wc_LoadStaticMemory", ret); + return ret; +} - if (buffer == NULL) { - return BAD_FUNC_ARG; + +void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap) +{ + WOLFSSL_ENTER("wc_UnloadStaticMemory"); + if (heap != NULL && heap->memory != NULL) { + wc_FreeMutex(&heap->memory->memory_mutex); } - - /* align pt */ - while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { - *pt = 0x00; - pt++; - ava--; - } - -#ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt); -#endif - - /* divide into chunks of memory and add them to available list */ - while (ava >= (heap->sizeList[0] + padSz + memSz)) { - /* creating only IO buffers from memory passed in, max TLS is 16k */ - if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - if ((ret = create_memory_buckets(pt, ava, - WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { - WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); - return ret; - } - - /* check if no more room left for creating IO buffers */ - if (ret == 0) { - break; - } - - /* advance pointer in buffer for next buckets and keep track - of how much memory is left available */ - pt += ret; - ava -= ret; - } - else { - 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 ((ret = create_memory_buckets(pt, ava, heap->sizeList[i], - heap->distList[i], &(heap->ava[i]))) < 0) { - WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); - return ret; - } - - /* advance pointer in buffer for next buckets and keep track - of how much memory is left available */ - pt += ret; - ava -= ret; - } - } - } - } - - return 1; } @@ -731,19 +750,19 @@ int wolfSSL_MemoryPaddingSz(void) /* Used to calculate memory size for optimum use with buckets. returns the suggested size rounded down to the nearest bucket. */ -int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +int wolfSSL_StaticBufferSz_ex(unsigned int listSz, + const unsigned int *sizeList, const unsigned int *distList, + byte* buffer, word32 sz, int flag) { - word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS}; - word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST}; - word32 ava = sz; byte* pt = buffer; word32 memSz = (word32)sizeof(wc_Memory); word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); - WOLFSSL_ENTER("wolfSSL_static_size"); + WOLFSSL_ENTER("wolfSSL_StaticBufferSz_ex"); - if (buffer == NULL) { + if (buffer == NULL || listSz > WOLFMEM_MAX_BUCKETS + || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } @@ -764,26 +783,39 @@ int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) else { int i, k; - if (ava < (bucketSz[0] + padSz + memSz)) { + if (ava < (sizeList[0] + padSz + memSz)) { return 0; /* not enough room for even one bucket */ } - while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { + while ((ava >= (sizeList[0] + padSz + memSz)) && (ava > 0)) { /* start at largest and move to smaller buckets */ - for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + for (i = (listSz - 1); i >= 0; i--) { for (k = distList[i]; k > 0; k--) { - if ((bucketSz[i] + padSz + memSz) <= ava) { - ava -= bucketSz[i] + padSz + memSz; + if ((sizeList[i] + padSz + memSz) <= ava) { + ava -= sizeList[i] + padSz + memSz; } } } } } + WOLFSSL_LEAVE("wolfSSL_StaticBufferSz_ex", sz - ava); return sz - ava; /* round down */ } +/* Calls wolfSSL_StaticBufferSz_ex with the static memory pool config + * used by wolfSSL by default. */ +int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +{ + word32 bucketSz[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_BUCKETS}; + word32 distList[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_DIST}; + + return wolfSSL_StaticBufferSz_ex(WOLFMEM_DEF_BUCKETS, bucketSz, distList, + buffer, sz, flag); +} + + int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) { WOLFSSL_MSG("Freeing fixed IO buffer"); diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 9702dab7a..714f56557 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -216,17 +216,22 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, byte haFlag; /* flag used for checking handshake count */ } WOLFSSL_HEAP_HINT; + WOLFSSL_API int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, + unsigned int listSz, const unsigned int *sizeList, + const unsigned int *distList, unsigned char* buf, unsigned int sz, + int flag, int max); 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); - WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap); - WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz, - int flag, WOLFSSL_HEAP* heap); - WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, + WOLFSSL_API int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats); WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + WOLFSSL_API int wolfSSL_StaticBufferSz_ex(unsigned int listSz, + const unsigned int *sizeList, const unsigned int *distList, + byte* buffer, word32 sz, int flag); WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag); WOLFSSL_API int wolfSSL_MemoryPaddingSz(void); #endif /* WOLFSSL_STATIC_MEMORY */