How to use the wolfSSL staticmemory feature

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