wolfTips: 静的メモリー割り当てを使いこなす

静的メモリー割り当てを wolfSSL で使用する。

wolfSSL を静的メモリー割り当てと共に使用することが出来ます。ただし、使用メモリー量が大きくなるので使用には気をつけなければならない面もあります。搭載メモリー量に比較的余裕のある環境での選択肢として使用できます。今回はその仕組みを紹介します。

 

まず、wolfSSL で静的メモリー割り当てを有効にし、ビルドを行います。ビルドは以下のオプションをconfigure に指定します。

$./configure –enable-staticmemory

静的メモリー割り当ては、USE_FAST_MATHマクロの定義が必要で、WOLFSSL_SMAL_STACK定義が未定義あることが必要となります。64 ビットの環境では、configureの実行でこれらが自動的に設定されます。64ビット以外の環境では、–enable-fastmath を指定します。ヘッダーファイルを使用する場合は、

#define WOLFSSL_STATIC_MEMORY

を指定します。

 

静的メモリー割り当ての仕組みはWOLFSSL_CTX構造体に静的バッファを割り当て、WOLFSSL_CTX構造体から派生・生成される各構造体にヒープヒントを渡し、各構造体でヒープヒントからメモリー割り当てを行うことで実現しています。次の図で矢印はヒープを、四角枠は構造体を示しています。

静的メモリー割り当てを有効にしたWOLFSSL_CTX構造体を生成するために、下記のAPIを使用します。

wolfSSL_CTX_load_static_memory()

動的メモリーの使用を避けるために、wolfSSL_CTX_load_static_memory()は、ctxをNULLで渡し、静的メソッド関数(_exで終わる)を使用して静的バッファメモリーのみを使用し WOLFSSL_CTX構造体を生成します。

 

静的メモリー割り当てを使用した例は、wolfSSL に含まれるデフォルトのクライアント/サーバー、及びCryptテストを参照することができます。

 

下記はクライアントの例になります。ファイルの先頭で静的メモリーバッファを確保し、WOLFSSL_CTX構造体の生成に、wolfSSL_CTX_load_static_memory() を利用していることがわかります。

#ifdef WOLFSSL_STATIC_MEMORY

#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
|| defined(SESSION_CERTS)
/* big enough to handle most cases including session certs */
byte memory[320000];
#else
byte memory[80000];
#endif
byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */
WOLFSSL_MEM_CONN_STATS ssl_stats;
#ifdef DEBUG_WOLFSSL
WOLFSSL_MEM_STATS mem_stats;
#endif

#endif

#ifdef WOLFSSL_STATIC_MEMORY

if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),
0, 1) != WOLFSSL_SUCCESS) {
err_sys(“unable to load static memory”);
}

 

if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO),
WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1) != WOLFSSL_SUCCESS) {
err_sys(“unable to load static memory”);
}

#else

ctx = wolfSSL_CTX_new(method(NULL));

#endif

静的メモリー割り当てのさらに詳しい内容については、静的バッファ割り当てドキュメントページ(英語)をご覧ください。いくつかの、特にOpenSSL互換レイヤのAPIは静的メモリーバッファの利用をサポートしていないものもありリストが掲載されています。併せて参照ください。

 

今回は静的メモリー割り当ての仕組みについて紹介しました。静的メモリーバッファを冒頭で用意するという特性上、動的メモリー割り当てと比較し多くのメモリーを消費する可能性があります。使用に際してはその特性を理解しお使い下さい。静的メモリー割り当ての使用に際し、ご質問等ありましたら、お気軽にsupport@wolfssl.com までお知らせください。

wolfTips: 証明書チェーンを理解する

階層になった証明書を wolfSSL で使用する

階層になった証明書を wolfSSL で使用する場合、その内部処理を理解しておくと使いやすさが抜群に向上します。今回は、証明書チェーンを検証する際の例を紹介し、wolfSSLの内部処理と共に見ていきたいと思います。

まず下記のように階層になった証明書があるとします。

 

これらの証明書のうち、中間サーバ公開鍵証明書をもつサーバを認証するには、認証用APIを用いて次のようにクライアント・サーバ間で引数を設定します。

// サーバサイド
wolfSSL_CTX_use_certificate_file( “中間サーバ公開鍵証明書「4」“)

// クライアントサイド
wolfSSL_CTX_load_verify_locations( “中間CA「3」“)

中間サーバ公開鍵証明書「4」に署名した中間CA「3」を使って検証することでクライアントはサーバを認証することが可能になります。

この時wolfSSL 内部では次図のようにCAを管理するためのCA管理用ハッシュテーブルが作成されます。インデックスのハッシュ値はサブジェクト鍵識別子から生成されます。

 

最初の例では証明書に署名したCAを直接読み込むことで認証を行いました。

 

では、ルートCA「1」使用し認証を行うためにはどうすれば良いのでしょう?

次のように証明書を読み込みます。

// サーバサイド
wolfSSL_CTX_use_certificate_file( “中間サーバ公開鍵証明書「2」+中間CA「3」“)

// クライアントサイド
wolfSSL_CTX_load_verify_locations( “ルートCA「1」“)

この時wolfSSLは先ほどと同様にCAを管理するためのCA管理用ハッシュテーブルを作成します。まずルートCAが最初に登録されます。次にルートCAによって検証された中間CAがテーブルに登録されます。中間サーバ公開鍵証明書は証明書に記述されたサブジェクト鍵識別子から、中間CAをテーブルから取り出します。取り出した中間CAを用いて検証を完了します。

 

wolfSSL に含まれる./certs フォルダの証明書を使って実際に試してみることも出来ます。まず最初の例、中間CAを直接ロードする場合、次のコマンドを使用します。

//サーバに中間公開鍵証明書をロード
$ ./examples/server/server -c ./certs/test-pathlen/server-1-cert.pem
//クライアントに中間CAをロード
$ ./examples/client/client -A ./certs/test-pathlen/server-1-ca.pem

次にルートCAを使用する場合は、次のように行います

//サーバ中間公開鍵証明書に中間CAを追記
$cat ./certs/test-pathlen/server-1-ca.pem >> ./certs/test-pathlen/server-1-cert.pem

//サーバに中間公開鍵証明書と中間CAをロード
$ ./examples/server/server -c ./certs/test-pathlen/server-1-cert.pem

//クライアントにルートCAをロード
$ ./examples/client/client

今回は階層になった証明書を検証するにあたって、APIに設定する引数とその内部処理について見てきました。実際の内部動作を頭にイメージでき、API使用時の手助けに少しでもなったら幸いです。証明書検証のAPI使用に際し、ご質問等ありましたら、お気軽にsupport@wolfssl.com までお知らせください。

 

wolfTips: テスト用デジタル証明書・鍵をつかいこなす

テスト用デジタル証明書・鍵、いろいろと取り揃えております。

wolfSSL では、テスト用にさまざまな証明書・鍵を揃えています。以前、少しだけ紹介しました。wolfTips : テスト用鍵、証明書(ファイルシステム有、無しの場合)

 

今回はさらにテスト用証明書・鍵の使い方をご紹介したいと思います。

 

サンプルサーバ、クライアントはデフォルトでは下記のものを参照します。

サーバ側証明書:./certs/server-cert.pem

サーバ側プライベート鍵:./certs/server-key.pem

クライアント側証明書:./certs/ca-cert.pem

 

楕円曲線暗号をサーバ認証に使用するには、下記の様に証明書を指定します。

サーバ側証明書:./certs/server-ecc.pem

サーバ側プライベート鍵:./certs/ecc-key.pem

クライアント側証明書:./certs/ca-ecc-cert.pem

 

$ ./examples/server/server  -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem

 

$ ./examples/client/client -A ./certs/ca-ecc-cert.pem

 

暗号アルゴリズム ed25519 をサーバ認証に使用するには、certs/ed25519ファルダ内の証明書を下記のように使用します。

サーバ側証明書:./certs/ed25519/server-ed25519.pem

サーバ側プライベート鍵;./certs/ed25519/server-ed25519-key.pem

クライアント側証明書:./certs/ed25519/root-ed25519.pem

 

$ ./examples/server/server -c ./certs/ed25519/server-ed25519.pem \

-k ./certs/ed25519/server-ed25519-key.pem

 

$ ./examples/client/client -A ./certs/ed25519/root-ed25519.pem -C

 

中間認証局による証明書を使用する場合、certs/intermediateフォルダ内の証明書を利用します。例えば、中間認証局によって署名されたサーバ証明書を使用する場合、対向テストには下記の証明書を利用します。

 

サーバ側証明書(中間認証局によって署名):./certs/intermediate/server-int-cert.pem

クライアント側証明書:./certs/intermediate/ca-int-cert.pem

$./examples/server/server -v 3 -c ./certs/intermediate/server-int-cert.pem -V -d

 

$ ./examples/client/client -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 \

-A ./certs/intermediate/ca-int-cert.pem -C

 

他にも下記の様にcerts/フォルダ内にはさまざまな証明書・鍵のファイルが存在します。基本的には、server サンプルプログラムの“-c” オプションでサーバ証明書、”-k”オプションでサーバの秘密鍵を指定します。また、client サンプルプログラムの”-A” でルート証明書を指定します。

./certs/1024 1024ビットの証明書・鍵ファイル
./certs/external パブリック認証局のルート証明書
ca/server/client-ecc384-xxx NIST 曲線 384 を使用する証明書・鍵ファイル
server/client-keyEnc フレーズ付きで暗号化された鍵ファイル

 

これらのファイルはテスト用に使用いただけます。使用に際し、ご質問等ありましたら、お気軽にsupport@wolfssl.comまでお知らせください。

 

wolfTips: 隠しコマンド!? TLSベンチマークテスト

もう一つベンチマークテストプログラムがあることをご存知ですか?

wolfSSLでは、ベンチマークテストのプログラムを提供していることを以前紹介しました。

wolfTips : ベンチマーク・プログラム

 

wolfSSL にはもう一つ別のベンチマークテストプログラムがあります。ソースレポジトリでは、下記に存在します。

/path/to/wolfSSL/examples/benchmark/tls_bench

前回ご紹介したベンチマークテストと区別する為に、TLSベンチマークテストと呼ぶことにします。今回はこのベンチマークテストプログラムをご紹介します。

 

早速、起動してみましょう。wolfSSL のルートフォルダから下記のように実行します。

$./examples/benchmark/tls_bench

 

下記は出力結果例です。

TLSベンチマークテストはServer/Client毎にスレッドを起動します。その後、ローカルマシン上でTLS通信を行いながら性能測定を実施し、デフォルトでは現在有効になっている全ての暗号スートについて測定を行います。

 

各出力項目は下記のような意味です。

上記から分かるように、送受信(write/readコマンド)実行に関する性能、TLS接続(ハンドシェーク)に関する性能を別々に測定しています。

 

これまでに登場した2つのテストプログラムに、TLSベンチマークテストプログラムを加え使用用途を場合分けすると、次のような使い分けが見えてきます。
 
1. 暗号アルゴリズムごとのベンチマークを行う場合
  → /wolfcrypt/test/testwolfcrypt

2. TCP/IP物理層を含む通信全体のベンチマークを行う場合

  → /examples/server/client

3. TLSハンドシェークとメッセージ送受信を区別しベンチマークを行う場合

  → /examples/benchmark/tls_bench

 

暗号アルゴリズム性能のみを評価したい場合、TLS通信も加味して性能測定を行いたい場合など用途にあわせてお使いください。また、デフォルト状態で実行する以外にもオプションスイッチをいくつか持っていますので、使用に際してご質問等ありましたらお気軽にsupport@wolfssl.com までお知らせください。

wolfTips: トラブルシューティング

繋がらない!最初にやることは:

準備万端、いざ接続…あれ、繋がらない!準備していても、少しの誤設定で問題は発生してしまいます。また組み込みという環境の性質上、問題発生時のデバック情報が少なく、解析に時間を要してしまうことがあります。
サポートに依頼しよう!そんな時、最初に思い出して頂きたい wolfSSLライブラリの必須デバックオプション、”–enable-debug” を紹介します。

使用方法は、”–enable-debug” オプションを指定し wolfSSL ライブラリをビルドします。
 $./configure --enable-debug
マクロ定義を使用する際は、DEBUG_WOLFSSL をヘッダーファイル(user_settings.h)に定義します。

あとはアプリケーション・プログラムの開始時に
 wolfSSL_Debugging_ON();
を呼び出します。

このオプションは、wolfSSL ライブラリのデバックメッセージ機能をオンにし、内部処理のトレースをデバックコンソールに出力します。得られたログをサポートへ送付頂くことで、処理の追跡が可能となりエラー解析の質が格段に向上します。

example/client/client を使用した際の出力例です。
初期のテスト構成はこちらを参照:wolfTips: 最初の対向テスト

ログをよく見ると
 wolfSSL Entering xxxx_yyy

 wolfSSL Leaving xxxx_yyy
というメッセージが見うけられます。これは xxxx_yyy という関数に入った(Entering)、そして処理終了後、離れた(Leaving)ということを示しています。
この例では、クライアントが間違ったCA証明書を使用しサーバ認証に失敗していました。正しい証明書を使用することでエラーを回避出来ました。

実際のエラーケースは、単純な場合から複数の要素が絡み合うものまで千差万別です。ちょっとした設定ミスでも、解析の方向を間違うと解決まで時間を要してしまうことがあります。今回紹介したデバックオプションで取得したログはデバックの方向を絞り込む上でとても有効です。
サポートへ現象とともにデバックログを送って頂くだけで問題解決はぐっと近くなります。デバックでお困りのことがあればお気軽にsupport@wolfssl.com までお知らせください。

wolfTips: デバック用オプション

メモリ使用状況が気になりますか?

wolfSSLには、多くのオプションスイッチがあります。その中には、事前に知っておくとその後のデバック効率が向上するものがあります。
今回はデバック時に有効なメモリ使用状況に関するオプションを紹介します。

使用方法は、configure にオプション “–enable-trackmemory” を指定し wolfSSL をビルドします。
$./configure --enable-trackmemory

マクロ定義を使用する場合は、WOLFSSL_TRACK_MEMORY を定義します。

後は、アプリケーション・プログラムの開始時に
InitMemoryTracker()
を呼び出し、メモリ使用状況を確認したい箇所で
ShowMemoryTracker()
を呼び出します。ShowMemoryTracker()は複数個所で呼び出しを行って構いません。メモリ使用状況を逐次確認するということも可能です。追加情報とし、これらの関数の呼び出しは、wolSSL_Init()及びwolfSSL_Cleanup()でそれぞれ自動的に行われます。

出力例は下記の通りです。

current Bytes に注目することでメモリリークの検出にも使用できます。

例として wolfSSL に同封されるtestwolfcrypt プログラムを “–enable-trackmemory” を指定しビルド・実行してみて下さい。

$ ./wolfcrypt/test/testwolfcrypt
error test passed!
base64 test passed!
asn test passed!
MD5 test passed!
……………
mutex test passed!
memcb test passed!
Test complete
total Allocs = 1445
total Deallocs = 1445
total Bytes = 4321945
peak Bytes = 71296
current Bytes = 0

“current Bytes = 0”。もちろんメモリリークしていません。

今回紹介したように wolfSSL ではアプリケーションのデバック作業効率を向上できるオプションがあります。個別環境でのデバック方法、特定の問題に対するデバックなどご質問ありましたらお気軽にsupport@wolfssl.com までお知らせください。

wolfTips: OpenSSL 互換APIを使いこなす

OpenSSL資産をムダにせず活用できます!

wolfSSLは、インプリメンテーション依存による脆弱性などを最小限にするためにクリーンルームによる独自開発のSSL/TLSライブラリです。一方で OpenSSL 互換の API も提供し既存の OpenSSL ユーザにも簡単にアプリケーションが開発できるように設計されています。ほかにも多くのオープンソースアプリケーションはOpenSSL 互換 API を使用し動作しています。

今回は、この wolfSSL のOpenSSL互換APIの使い方を紹介します。

1.wolfSSLライブラリのビルド

デフォルトで wolfSSL ライブラリのビルドシステムは、OpenSSL 互換 API を無効にしています。OpenSSL互換APIを有効にするには、configure で”–enable-opensslextra”オプションを指定します。

$./configure --enable-opensslextra
“–enable-opensslextra” 以外に、”–enable-opensslall”というオプションが指定可能です。”–enable-opensslall”オプションは、wolfSSL でサポートしている OpenSSL 互換API を使用頻度の低いものも含めて有効化します。

 2.アプリケーションのビルド

OpenSSL APIを使用するアプリケーションをwolfSSL OpenSSL互換APIを用いてビルドするには gcc の場合以下のオプションを指定して行います。

  • ヘッダーファイルパスに wolfSSL ヘッダーファイルのインストール先を指定します。
    gcc の場合:
    -I /path/to/wolfssl/wolfssl -I /path/to/wolfssl
  • wolfssl/openssl/ssl.hをincludeオプションを使用し、直接インクルードします
    -include wolfssl/options.h
  • wolfSSLライブラリをリンクします。
    gcc の場合:
    -lwolfsslを指定します。

次のプログラムはTLSサーバに接続し、”Hello”を送信するだけの簡単なOpenSSL API 使用のサンプルです。ソースコードを変更することなく wolfSSL ライブラリと共に動作させることができます。

/* simplified echoclient wolfSSL and OpenSSL */
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "echoclient.h"

void hello_test()
{
    const char* msg = "Hello SSL!\n";
    SSL_CTX*    ctx = 0;
    SSL*        ssl = 0;
    int ret = 0, err = 0;
    int sendSz;
    char buffer[MAX_ERROR_SZ];
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in servaddr;

    /* server information */
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(11111);
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    /* init library */
    SSL_library_init();
    /* create a new CTX */
    ctx = SSL_CTX_new(SSLv23_client_method());
    /* set default locations for trusted CA certificates */
    if (SSL_CTX_load_verify_locations(ctx, caCertFile, 0) != SSL_SUCCESS)
        printf("can't load ca-ecc file.\n");    
    /* create a new SSL structure for a connection */
    ssl = SSL_new(ctx);
    /* connect socket */
    connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
    /* connect the SSL object with a file descriptor */
    SSL_set_fd(ssl, sockfd);
    /* initiate the TLS/SSL handshake with an TLS/SSL server */
    err = 0; /* Reset error */
    ret = SSL_connect(ssl);
    if (ret != SSL_SUCCESS) {
        err = SSL_get_error(ssl, 0);
        printf("SSL_connect error %d, %s\n", err,
        ERR_error_string(err, buffer));
    }
    /* send message to server */
    sendSz = (int)strlen(msg);
    do {
        err = 0; /* reset error */
        ret = SSL_write(ssl, msg, sendSz);
        if (ret <= 0) {
            err = SSL_get_error(ssl, 0);
        }
    } while (err == _WANT_WRITE);
    /* clean up */
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    /* close descriptor */
    close(sockfd);
}
/* entry */
int main()
{
    hello_test();
    return 0;
}
コンパイル例 (gccの場合):
$gcc -o hello_wolfssl hello.c -I/path/to/wolfssl -I/path/to/wolfssl/wolfssl -include wolfssl/options -lwolfssl

上記のサンプルプログラムのようにOpenSSL互換APIを利用することで、簡単に既存のOpenSSLソースコードを再利用することができます。

3. サポート済み互換APIの確認方法

OpenSSLのAPIは膨大なため、wolfSSL では使用頻度の高いAPIのサブセットを提供しています。必要なOpenSSL APIがサポートされているかは、以下の3ステップを行い判断することができます。

  • /wolfssl/opensslディレクトリ内のヘッダーファイルを確認する。
    /wolfssl/opensslディレクトリ内のヘッダーには OpenSSL 互換レイヤのAPI定義を含む記述があります。 このフォルダ内のssl.hに定義があるかを確認します。
  • NO_WOLFSSL_STUBを定義しアプリケーションのリンクを行ってみる
    APIによっては関数の定義のみで、内部の実装が行われていないものも存在します。そのようなAPIを検出するために次のステップを行います。
  1. configure に NO_WOLFSSL_STUB マクロ定義を指定します。
    $./configure –enable-opensslextra CFLAGS=”-DNO_WOLFSSL_STUB”
    SSL_CTX_get_mode() を例にとって試してみます。
    /wolfssl/openssl/ssl.h を確認します。

    #define SSL_CTX_set_mode                wolfSSL_CTX_set_mode
    #define SSL_CTX_get_mode                wolfSSL_CTX_get_mode
    #define SSL_CTX_set_default_read_ahead  wolfSSL_CTX_set_default_read_ahead
    

    SSL_CTX_get_modeは、wolfSSL_CTX_get_mode に対応付けられています。

  2. 次に、src/ssl.c内にあるwolfSSL_CTX_get_modeの実装を確認してみます。
    #ifndef NO_WOLFSSL_STUB
    long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
    {
        /* TODO: */
        (void)ctx;
        WOLFSSL_STUB("SSL_CTX_get_mode");
        return 0;
    }
    #endif
    

    未実装で、#ifndef #endif で括られていることが分かります。

  3. NO_WOLFSSL_STUB を指定し、wolfSSL ライブラリをビルドします。
    $./configure –enable-opensslextra CFLAGS=”-DNO_WOLFSSL_STUB”
    $make

    先ほどのアプリケーションにSSL_CTX_get_mode() 呼び出しを追加し、コンパイルしてみます。

    $gcc -o hello_wolfssl hello.c -I/path/to/wolfssl -I/path/to/wolfssl/wolfssl -include wolfssl/options -lwolfssl
    /tmp/cco4upmi.o: 関数 `hello_test' 内:
    echoclient.c:(.text+0xf6): `wolfSSL_CTX_get_mode' に対する定義されていない参照です
    collect2: error: ld returned 1 exit status

    エラーになり、実装されていないことが分かります。

4. 注意事項

サポート済みAPIの有無以外にOpenSSL互換APIを使用する上で注意しておく点があります。

  • 構造体に互換性がない

構造体の互換性を保証しませんので、構造体メンバーを直接参照は避けてください。

  • エラーチェック・エラーコードに互換性がない

API内部の実装が、まったくの同一ではないため、エラーチェックの段階で異なる戻り値を返すことがあります。下記に一例を挙げます。
例:SSL_CTX_load_verify_locations()

エラーの条件wolfSSLOpenSSL
指定した CA ファイルが存在しない-4(WOLFSSL_BAD_FILE)0(失敗)
CA ファイルの有効期限が無効(有効期限前)-150(ASN_BEFORE_DATE_E)1(成功)
成功1(WOLFSSL_SUCCESS)1(成功)

サポート済みAPIの確認方法、及び注意点で言及しましたように気を付けるポイントがいくつかありますが、今回紹介したように wolfSSL ではOpenSSL からのアプリケーションの移行に配慮しています。また、サポート済みAPIの有無、その動作についてや新たなAPIの追加サービスのご希望などありましたらお気軽にsupport@wolfssl.com までお知らせください。

 

wolfTips: ベンチマーク・プログラム

wolfSSLの処理時間が気になりますか?

wolfSSLサイトのベンチマークページには、さまざまな異なる条件でのベンチマーク結果を掲載しています。しかし、TLSは使われる暗号化スイートや個別のアルゴリズム、ネットワークの諸条件によって処理時間が大きく異なってきます。wolfSSLの使用される実際の対象ハードウェア、ネットワークや開発環境は多様であるため、一般的な処理性能を提示することはなかなか難しいことです。そのために、wolfSSLではお客さまの実際の環境でベンチマークテストができるように製品と同梱でベンチマークプログラムを提供しています。

ここでは、製品に含まれている二つのベンチマーク機能とその使い方について紹介します。

一つ目は、暗号アルゴリズムレイヤーでのベンチマークプログラムです。このプログラムではTLSで使われる個々の暗号アルゴリズムについて、実機での処理性能を評価することができます。このベンチマークプログラムは、もちろん各アルゴリズムが目標通りの性能を発揮しているかどうか確認するために利用できますが、そのほかにも以下のような色々な目的で使用することができます。

  • コンパイラーの最適化レベルが暗号処理の性能にどのくらい影響するか知りたい
  • wolfSSLの持っている整数演算ライブラリーのうちどれが目的のシステムに一番有効か知りたい
  • ハードウェア暗号アクセラレータとソフトウェア暗号化の性能を比較したい
  • 暗号スイートを選択するときのアルゴリズム個別の基本的な性能データが知りたい

もう一つは、TLSプロトコル層とそれ以下のネットワーク層を含めた通信全体の性能をベンチマークするための機能です。このベンチマークはTLSサーバとクライアントのサンプルプログラムの中のオプション機能を使って評価します。

 

1. /wolfcrypt/benchmark/benchmark

暗号アルゴリズム毎のベンチマークを測定するプログラムです。暗号アルゴリズム単位の性能を知るのに有効で、性能評価の最初のステップのツールとしてお勧めです。

ブロック暗号及びストリーム暗号は、ブロック単位で測定時間以上、暗号化・復号化を繰り返し行いその回数から性能を計算します。公開鍵暗号は測定時間以上、鍵生成・合意・認証・証明操作を何回行えたかで性能を計算します。出力結果と各部位の意味するところを出力例で次の図に示します。

2./examples/client and server

benchmark プログラムは暗号アルゴリズム単独でのパフォーマンス測定するのに対して、次のステップでは、より実環境に近い状態で速度性能を測定したいとの要求もあります。

TLSの処理性能には接続時のハンドシェイク処理とアプリケーションメッセージ転送の二つのファクターがあります。接続時のハンドシェイク処理は、アプリケーションメッセージの長さに依存せず一定の時間がかかります。それに対して、メッセージ転送時間は概ね転送するメッセージのサイズに比例した時間がかかります。

そのような計測には、/examples/client/client及び/examples/server/server の両プログラムを使用することが出来ます。それぞれについて、次のようなオプションを使用します。

  • 接続時間の計測:client の -b <num>オプション、serverの -C <num> オプション, -iオプション
  • メッセージ転送時間の計測:server / client の -B <data size>オプション

client -b <num> は、TLSハンドシェークをnum回数実施しその平均値を出力します。下記は、10 回 TLS 1.3 ハンドシェークを実施したその平均値を出力する例です。

クライアント側:
$ ./examples/client/client -v 4 -h 192.168.11.18 -d -b 10
wolfSSL_connect avg took:  970.207 milliseconds

サーバ側:
$ ./examples/server/server -v 4 -C 10
または
$ ./examples/server/server -v 4 -i

外部のサーバーに対しても行うことが出来ます。下記の例では、www.googld.com のポート443に対して10回TLS接続を行いその平均値を出力します。

$ ./examples/client/client -h www.google.com -p 443 -d -b 10
wolfSSL_connect avg took:  108.224 milliseconds

 

メッセージ送受信部分の速度性能を知りたい場合には server/client -B オプションを次のように使います。

  1. 転送メッセージ・サイズを設定します。例:1M Byte(≒1048576 byte)
  2. 注目する開発環境でビルドした ./examples/server/server を起動します。
    $ ./examples/server/server -b -d -i -B 1048576
    他の引数は次のような意味を持ちます
    -b : ローカルホスト以外のインターフェースへもバインドする
    -d : クライアント認証を無効とする
    -i : 無期限にループする(繰り返し接続を許可)
  3. 計測したいネットワーク環境で接続された別ターミナルで./examples/client/client を起動します。
    $ ./examples/client/client -h 192.168.11.24 -B 1048576
  4. 出力を確認します。

    client サイドの出力例は次のようになります。

更に暗号スイートをいくつか変更し、そのスイート毎の性能を比較したいという場合、client プログラムの “-e” 及び “-l” を使用します。次の例のように行います。

  1. client プログラムの “-e” でサポートする暗号スイートを調べます。
    $ ./examples/client/client -e
    DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-
    AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-
    SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-
    SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-
    POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305-OLD:TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-
    CHACHA20-POLY1305-SHA256
    
  2. client プログラムの “-l” オプションで、使用したい暗号スイートを選択します。
    $ ./examples/client/client -h 192.168.11.25 -l ECDHE-ECDSA-AES128-GCM-SHA256 -d
    “-l”オプションで指定する暗号スイートは、”-e”オプションで得た文字列をそのまま入力として使用します。前述の “-d” 及び “-B” オプションと組み合わせてご使用下さい。

wolfTips: 新しい整数演算ライブラリ

TLSの性能に関して一番気になるのはハンドシェイク処理時間ではないだろうか。処理時間的に見るとハンドシェイク処理でほとんどの時間は鍵交換、デジタル署名や検証など公開鍵暗号の処理に費やされている。この公開鍵暗号はご存じの通り大きな整数値のベキ乗や剰余の演算処理だ。

wolfSSLではこの大きな整数値の演算のために特別なライブラリを提供しており、時代とともに改良を加えている。初期に、どのようなアーキテクチャのMPUでもポータブルかつ高速に動作するように特別に開発された標準整数ライブラリ(integer.c)は今でもwolfSSLのデフォルト整数ライブラリだ。これに対して、Tom’s Fast Math をベースにIntelアーキテクチャやARMアーキテクチャで特に高速に動作するように改良を加えたFast Math (tfm.c)。これまで、これら二つをターゲット環境に応じてビルドオプションで使い分けてきた。

最近加えられたもう一つのオプションは、公開鍵処理に特化したSingle Precisionオプションだ。公開鍵の整数演算で特定の鍵長であればループ処理を使わなくても直線的な処理に落とし込むことができることを利用し、高速化と処理時間の一定化を実現したものだ。そういうわけでSingle Precisionと言っても、フローティングポイントの単精度とは関係ない、あえて日本語訳するとすれば、単一精度ないし特定精度というようなことになるだろう。

このSingle Precisionオプションは、configureコマンドならば

$ ./configure –enable-sp

というような形で簡単に定義することができる。Single Precision処理は原理的にアルゴリズムや鍵長ごとに対応しなければならない。現在のところwolfSSLではRSA/DH 2048/3072, ECDSA/ECDH256 の署名、鍵交換に対応している。

./wolfcrypt/benchmark/benchmark

でベンチマークを比較することができるので、ぜひご自分の実機で比較して見てください。

特にIoTでは、アプリケーションメッセージの送受信よりハンドシェイク処理時間の方が目立つことが多い。そいう場合のチューニングにおすすめできるオプションだ。また、この処理は処理時間が一定化され、サイドチャネル攻撃に対して耐性が向上するというセキュリティ上の利点からもおすすめです。

wolfSSL Japan技術サポートチーム

wolfTips: テスト用鍵、証明書 (ファイルシステム有, 無しの場合)

wolfSSLでは、ユーザが作ったプログラムをテストする際にすぐ使えるようなテスト用の鍵や証明書のファイルを製品といっしょに提供しています。certsディレクトリの直下には、サーバー認証、クライアント認証に使用する公開鍵証明書、プライベート鍵(RSA, ECC)がDERとPEMフォーマットで格納されていますのでご利用ください。また、CRLやOCSP用のファイルもそれぞれのディレクトリに格納されています。

例えば、製品に含まれているTLSサーバーとクライアントのサンプルプログラムのデフォルトでは、サーバ認証のためには次の各ファイルが使われていて、RSAによる認証を行います。

サーバー側証明書:./certs/server-cert.pem

サーバー側プライベート鍵;./certs/server-key.pem

クライアント側証明書:./certs/ca-cert.pem

これに対して、例えば次のような各ファイルを指定すれば楕円曲線暗号によるサーバー認証を実行することができます。

./examples/server/server -k ./certs/ecc-key.pem -c ./certs/server-ecc.pem

./examples/client/client -A ./certs/ca-ecc-cert.pem

 

ファイルシステム無しの場合のテスト用には、wolfssl/certs_test.hヘッダーファイルにC 言語によるデータ定義ファイルが提供されています。このファイルには、上記のcerts直下の各ファイルに対応したデータ定義が格納されています。このファイルをインクルードして、あらかじめ定義されたデータを使ってテストすることができるようになっているのでぜひご利用ください。

Posts navigation

1 2