wolfSSL is an embedded cryptographic library that includes a TLS/DTLS implementation. For resource-constrained devices or safety-critical applications, dynamic memory allocation via malloc and free system calls may be unavailable. To address these scenarios, wolfSSL offers the –enable-staticmemory feature. This feature provides a robust and straightforward allocation mechanism as an alternative. It utilizes a pre-allocated buffer, segmenting it into sections that applications can acquire by calling XMALLOC and release back to the memory pool using XFREE.
To activate this feature, compile wolfSSL using ./configure –enable-staticmemory or, if utilizing a user_settings.h file, define WOLFSSL_STATIC_MEMORY. Subsequently, execute make. Following compilation, the application must invoke wc_LoadStaticMemory to designate the buffer for partitioning and utilization, and then transmit the resulting “heap hint” to all XMALLOC and XFREE calls. By default, XMALLOC and XFREE calls will revert to the system’s malloc and free if no “heap hint” is provided. To circumvent all system malloc and free calls, the macro WOLFSSL_NO_MALLOC can be defined. For instance, this can be achieved via ./configure –enable-staticmemory CPPFLAGS=-DWOLFSSL_NO_MALLOC.
An additional option available, introduced in wolfSSL version 5.7.0 and subsequent releases, is the utilization of a globally defined “heap hint.” This global heap hint is established by invoking the setter function void* wolfSSL_SetGlobalHeapHint(void* heap). Consequently, any invocation of XMALLOC or XFREE that receives a NULL pointer as the “heap hint” will default to employing the globally configured “heap hint” pointer.
Setting up the memory sizes to use for each of the sections can be a difficult problem. To help some with a base configuration of the memory sizes there is a relatively new memory “bucket” optimizer tool located in the wolfssl-examples repository. It takes in the logging output of memory allocation calls from an application and provides a suggested static memory configuration based on the results. It’s possible in some cases to get even more optimized with the configuration but this example application gives a very good starting point.
The following is an example output when providing the memory logs of testwolfcrypt to the optimizer:
Building wolfSSL and collecting memory usage logs
$ ./configure --enable-staticmemory CPPFLAGS="-DWOLFSSL_DEBUG_MEMORY -DWOLFSSL_DEBUG_MEMORY_PRINT" -q && make > /dev/null && ./wolfcrypt/test/testwolfcrypt &> testwolfcrypt.log
Running the optimizer application on the resulting memory usage log
$ make gcc -o memory_bucket_optimizer memory_bucket_optimizer.c -lwolfssl $./memory_bucket_optimizer testwolfcrypt.log Found 24 unique allocation sizes Peak heap usage: 60074 bytes (maximum concurrent memory usage) Allocation Sizes, Frequencies, and Concurrent Usage: Size Count Max Concurrent ---- ----- -------------- 4208 1 1 3128 914 19 2112 85 1 1600 13 1 1120 13 1 1040 1 1 1024 4 2 800 37 1 257 65 2 256 9 1 235 7 1 227 5 1 223 5 1 207 5 1 191 5 1 136 5 1 128 8 1 104 5 1 72 5 1 64 6 1 48 5 1 32 2 1 28 1 1 0 0 0 Optimization Summary: Padding size per bucket: 32 bytes Maximum unique buckets allowed: 9 Total buckets created: 9 Note: Reached maximum bucket limit (9). Some allocations may use larger buckets. Note: Allocations with waste < padding size use existing buckets to reduce overhead Note: Bucket limit helps balance memory efficiency vs. management overhead Optimized Bucket Sizes and Distribution: Data Size + Padding = Bucket Size Dist ---------------------------------------- 272 + 32 = 304 2 800 + 32 = 832 1 1024 + 32 = 1056 2 1040 + 32 = 1072 1 1120 + 32 = 1152 1 1600 + 32 = 1632 1 2112 + 32 = 2144 1 3136 + 32 = 3168 19 4208 + 32 = 4240 1 WOLFMEM_BUCKETS and WOLFMEM_DIST Macros: #define WOLFMEM_BUCKETS 304,832,1056,1072,1152,1632,2144,3168,4240 #define WOLFMEM_DIST 2,1,2,1,1,1,1,19,1 Memory Efficiency Analysis: Note: Allocations with waste < 32 bytes (padding size) use existing buckets Size Count Concurrent Bucket Waste Coverage ---- ----- ---------- ------ ----- -------- 4208 1 1 4240 0 ? 3128 914 19 3168 8 ? 2112 85 1 2144 0 ? 1600 13 1 1632 0 ? 1120 13 1 1152 0 ? 1040 1 1 1072 0 ? 1024 4 2 1056 0 ? 800 37 1 832 0 ? 257 65 2 304 15 ? 256 9 1 304 16 ? 235 7 1 304 37 ? 227 5 1 304 45 ? 223 5 1 304 49 ? 207 5 1 304 65 ? 191 5 1 304 81 ? 136 5 1 304 136 ? 128 8 1 304 144 ? 104 5 1 304 168 ? 72 5 1 304 200 ? 64 6 1 304 208 ? 48 5 1 304 224 ? 32 2 1 304 240 ? 28 1 1 304 244 ? 0 0 0 304 272 ? Efficiency Summary: Total allocations: 1206 Allocations handled: 1206 (100.0%) Total memory waste: 16654.00 bytes Average waste per allocation: 13.81 bytes Total bucket memory: 73984 bytes Memory overhead: 1239 bytes - Padding per bucket: 32 bytes (included in bucket sizes) - Heap structures: 296 bytes - Alignment: 15 bytes Total memory needed: 75223 bytes Data memory: 3141010 bytes Buffer Size Recommendations: ============================ Minimum buffer size needed: 75224 bytes Usage in wolfSSL application: ============================ // Allocate buffer byte staticBuffer[75224]; // Load static memory WOLFSSL_HEAP_HINT* heapHint = NULL; if (wc_LoadStaticMemory_ex(&heapHint, 9, bucket_sizes, bucket_dist, staticBuffer, 75224, 0, 0) != 0) { // Handle error } // Use in wolfSSL context wolfSSL_CTX_load_static_memory(&method, NULL, staticBuffer, 75224, 0, 1);
Additional documentation about the staticmemory feature can be found in the wolfSSL manual.
If you have questions about any of the above, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.
Download wolfSSL Now