From e8f7d78fc412d303208c9ecc5eb455638904d2ab Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 21 Jul 2016 12:11:15 -0600 Subject: [PATCH] add helper functions for choosing static buffer size --- examples/server/server.c | 12 +++++ src/ssl.c | 19 ++----- wolfcrypt/src/memory.c | 56 ++++++++++++++++++++ wolfcrypt/test/test.c | 105 +++++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/memory.h | 23 +++++++- 5 files changed, 198 insertions(+), 17 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 0fdbdd2e6..b5dc3de2d 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -632,6 +632,18 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) err_sys("unable to get method"); #ifdef WOLFSSL_STATIC_MEMORY + #ifdef DEBUG_WOLFSSL + /* print off helper buffer sizes for use with static memory + * printing to stderr incase of debug mode turned on */ + fprintf(stderr, "static memory management size = %d\n", + wolfSSL_MemoryPaddingSz()); + fprintf(stderr, "calculated optimum general buffer size = %d\n", + wolfSSL_StaticBufferSz(memory, sizeof(memory), 0)); + fprintf(stderr, "calculated optimum IO buffer size = %d\n", + wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO), + WOLFMEM_IO_POOL_FIXED)); + #endif /* DEBUG_WOLFSSL */ + if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),0,1) != SSL_SUCCESS) err_sys("unable to load static memory and create ctx"); diff --git a/src/ssl.c b/src/ssl.c index fab0feed3..a44bcb8ec 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -643,16 +643,8 @@ int wolfSSL_GetObjectSize(void) int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) { - /* default size of chunks of memory to seperate into - * having session certs enabled makes a 21k SSL struct */ -#ifndef SESSION_CERTS - word32 wc_defaultMemSz[WOLFMEM_DEF_BUCKETS] = - { 64, 128, 256, 512, 1024, 2432, 3456, 4544, 16128 }; -#else - word32 wc_defaultMemSz[WOLFMEM_DEF_BUCKETS] = - { 64, 128, 256, 512, 1024, 2432, 3456, 4544, 21056 }; -#endif - word32 wc_defaultDist[WOLFMEM_DEF_BUCKETS] = { 8, 4, 4, 12, 4, 5, 2, 1, 1 }; + word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; if (heap == NULL) { return BAD_FUNC_ARG; @@ -660,11 +652,8 @@ int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); - /* default pool sizes and distribution, else leave a 0's for now */ - #if WOLFMEM_DEF_BUCKETS == WOLFMEM_MAX_BUCKETS - XMEMCPY(heap->sizeList, wc_defaultMemSz, sizeof(wc_defaultMemSz)); - XMEMCPY(heap->distList, wc_defaultDist, sizeof(wc_defaultMemSz)); - #endif + XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); + XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); if (InitMutex(&(heap->memory_mutex)) != 0) { WOLFSSL_MSG("Error creating heap memory mutex"); diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 53b341fd1..1f7efe1ee 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -263,6 +263,62 @@ int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, } +/* 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) +{ + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + return memSz + padSz; +} + + +/* 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) +{ + 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"); + + if (buffer == NULL) { + return BAD_FUNC_ARG; + } + + /* align pt */ + while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + pt++; + ava--; + } + + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + ava = sz % (memSz + padSz + WOLFMEM_IO_SZ); + } + else { + int i, k; + while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + for (k = distList[i]; k > 0; k--) { + if ((bucketSz[i] + padSz + memSz) <= ava) { + ava -= bucketSz[i] + padSz + memSz; + } + } + } + } + } + + return sz - ava; /* round down */ +} + + int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) { WOLFSSL_MSG("Freeing fixed IO buffer"); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9d69a952d..05321dbaa 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -248,6 +248,9 @@ int certext_test(void); #ifdef HAVE_IDEA int idea_test(void); #endif +#ifdef WOLFSSL_STATIC_MEMORY +int memory_test(void); +#endif /* General big buffer size for many tests. */ #define FOURK_BUF 4096 @@ -532,6 +535,13 @@ int wolfcrypt_test(void* args) else printf( "RANDOM test passed!\n"); +#ifdef WOLFSSL_STATIC_MEMORY + if ( (ret = memory_test()) != 0) + return err_sys("MEMORY test failed!\n", ret); + else + printf( "MEMORY test passed!\n"); +#endif + #ifndef NO_RSA if ( (ret = rsa_test()) != 0) return err_sys("RSA test failed!\n", ret); @@ -3857,6 +3867,101 @@ int random_test(void) #endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#ifdef WOLFSSL_STATIC_MEMORY +int memory_test(void) +{ + int ret = 0; + unsigned int i; + word32 size[] = { WOLFMEM_BUCKETS }; + word32 dist[] = { WOLFMEM_DIST }; + byte buffer[30000]; /* make large enough to involve many bucket sizes */ + + /* check macro settings */ + if (sizeof(size)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { + return -97; + } + + if (sizeof(dist)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { + return -98; + } + + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((size[i] % WOLFSSL_STATIC_ALIGN) != 0) { + /* each element in array should be divisable by alignment size */ + return -99; + } + } + + for (i = 1; i < WOLFMEM_MAX_BUCKETS; i++) { + if (size[i - 1] >= size[i]) { + return -100; /* sizes should be in increasing order */ + } + } + + /* check that padding size returned is possible */ + if (wolfSSL_MemoryPaddingSz() <= WOLFSSL_STATIC_ALIGN) { + return -101; /* no room for wc_Memory struct */ + } + + if (wolfSSL_MemoryPaddingSz() < 0) { + return -102; + } + + if (wolfSSL_MemoryPaddingSz() % WOLFSSL_STATIC_ALIGN != 0) { + return -103; /* not aligned! */ + } + + /* check function to return optimum buffer size (rounded down) */ + if ((ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_GENERAL)) + % WOLFSSL_STATIC_ALIGN != 0) { + return -104; /* not aligned! */ + } + + if (ret < 0) { + return -105; + } + + if ((unsigned int)ret > sizeof(buffer)) { + return -106; /* did not round down as expected */ + } + + if (ret != wolfSSL_StaticBufferSz(buffer, ret, WOLFMEM_GENERAL)) { + return -107; /* retrun value changed when using suggested value */ + } + + ret = wolfSSL_MemoryPaddingSz(); + if (wolfSSL_StaticBufferSz(buffer, size[0] + ret + 1, WOLFMEM_GENERAL) != + (ret + (int)size[0])) { + return -108; /* did not round down to nearest bucket value */ + } + + ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_IO_POOL); + if (ret < 0) { + return -109; + } + + if ((ret % (WOLFMEM_IO_SZ + wolfSSL_MemoryPaddingSz())) != 0) { + return -110; /* not even chunks of memory for IO size */ + } + + if ((ret % WOLFSSL_STATIC_ALIGN) != 0) { + return -111; /* memory not aligned */ + } + + /* check for passing bad or unknown argments to functions */ + if (wolfSSL_StaticBufferSz(NULL, 1, WOLFMEM_GENERAL) > 0) { + return -112; + } + + if (wolfSSL_StaticBufferSz(buffer, 1, WOLFMEM_GENERAL) != 0) { + return -113; /* should round to 0 since struct + bucket will not fit */ + } + + return 0; +} +#endif /* WOLFSSL_STATIC_MEMORY */ + + #ifdef HAVE_NTRU byte GetEntropy(ENTROPY_CMD cmd, byte* out); diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 274787939..cd44741b4 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -71,10 +71,26 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, #ifdef WOLFSSL_STATIC_MEMORY #define WOLFSSL_STATIC_TIMEOUT 1 - #define WOLFSSL_STATIC_ALIGN 16 - #define WOLFMEM_MAX_BUCKETS 9 + #ifndef WOLFSSL_STATIC_ALIGN + #define WOLFSSL_STATIC_ALIGN 16 + #endif + #ifndef WOLFMEM_MAX_BUCKETS + #define WOLFMEM_MAX_BUCKETS 9 + #endif #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ + #ifndef WOLFMEM_BUCKETS + /* default size of chunks of memory to seperate into + * having session certs enabled makes a 21k SSL struct */ + #ifndef SESSION_CERTS + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,16128 + #else + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,21056 + #endif + #endif + #ifndef WOLFMEM_DIST + #define WOLFMEM_DIST 8,4,4,12,4,5,2,1,1 + #endif /* flags for loading static memory (one hot bit) */ #define WOLFMEM_GENERAL 0x01 @@ -147,6 +163,9 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, 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(byte* buffer, word32 sz, int flag); + WOLFSSL_API int wolfSSL_MemoryPaddingSz(void); #endif /* WOLFSSL_STATIC_MEMORY */ #ifdef __cplusplus