wolfSSLにおける静的メモリ割当機能の使い方

wolfSSLは、TLS/DTLS実装を含む組み込み向け暗号化ライブラリです。リソース制約のあるデバイスやセキュリティが重要なアプリケーションでは、mallocおよびfreeシステムコールによる動的メモリ割り当てが利用できない場合があります。
これらのシナリオに対処するため、wolfSSLは--enable-staticmemory機能を提供しています。この機能は、代替手段として堅牢で分かりやすい割り当てメカニズムを提供します。これは事前割り当てされたバッファを利用し、それをセクションに分割します。アプリケーションはXMALLOCを呼び出してセクションを取得し、XFREEを使用してメモリプールに解放します。

この機能を有効にするには、設定時に./configure --enable-staticmemoryを使用するか、user_settings.hファイルを使用している場合はWOLFSSL_STATIC_MEMORYを定義します。
その後、makeを実行します。コンパイル後、アプリケーションはwc_LoadStaticMemoryを呼び出して、分割と利用のためのバッファを指定し、結果として得られる「ヒープヒント」をすべてのXMALLOCおよびXFREE呼び出しに送信する必要があります。
デフォルトでは、この「ヒープヒント」が提供されない場合、XMALLOCおよびXFREE呼び出しはシステムのmallocおよびfreeを使用します。一切のシステムmallocおよびfree呼び出しを回避するには、マクロWOLFSSL_NO_MALLOCを定義します。たとえば、./configure --enable-staticmemory CPPFLAGS=-DWOLFSSL_NO_MALLOCのようにします。

wolfSSL v5.7.0以降では、グローバルに定義されたヒープヒントを利用できるようになりました。
このグローバルヒープヒントは、setter関数void* wolfSSL_SetGlobalHeapHint(void* heap)を呼び出すことで確立されます。その結果、ヒープヒントとしてNULLポインタを受け取るXMALLOCまたはXFREEの呼び出しは、デフォルトでグローバルに構成されたヒープヒントポインタを使用します。

各セクションにおいて使用するメモリサイズをどのように設定すべきか、そう簡単に定められるものではありません。そこで、メモリサイズの基本構成をサポートするために、wolfssl-examplesリポジトリにてメモリバケット最適化ツールを提供しています。
このツールはアプリケーションからのメモリ割り当て呼び出しのログ出力を受け取り、結果に基づいて推奨される静的メモリ構成を提供します。場合によっては構成をさらに最適化することも可能ですが、チューニングの出発点として本ツールの使用を推奨しています。

以下は、testwolfcryptのメモリログを最適化ツールに提供した場合の出力例です。

wolfSSLのビルドとメモリ使用ログの収集

$ ./configure --enable-staticmemory CPPFLAGS="-DWOLFSSL_DEBUG_MEMORY -DWOLFSSL_DEBUG_MEMORY_PRINT" -q && make > /dev/null && ./wolfcrypt/test/testwolfcrypt &> testwolfcrypt.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);

静的メモリ割り当て機能に関するさらなる情報は、wolfSSLドキュメント 第4章をご覧ください。

ご質問がございましたら、ぜひ info@wolfssl.jp までお問い合わせください。

原文:https://www.wolfssl.com/how-to-use-the-wolfssl-staticmemory-feature