1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

mbedTLSの概要とコンフィギュレーション

Posted at

下記の記事にて、SSL/TLSに関してまとめ、NUCLEOF429Ziを使用した場合のmbedTLSのハンズオンとしての記事も作成しました。

ただ、mbedTLSの設定方法に関してはあまり触れていなかったので、本記事でこのあたりを説明しようと思います。
長くなってしまったので、初期化時のソースコードと通信する際のソースコードに関しては別の記事にて書く予定です。

mbedTLSとは

mbedTLSとは、組み込み開発で使用できるように作られた軽量型のSSL/TLSライブラリです。ソフトウェアの構成として図を示すと、mbedTLSは下記の場所に位置します。

ソフトウェア構成.png

mbedTLSは、EthernetなどのデバイスドライバとTCPIPのプロトコルスタックによる通信ができることが前提となっております。使用するハードウェアに暗号プロセッサや乱数発生器等が搭載されている場合は、TCPIPのプロトコルスタックを介さずにこれらのデバイスドライバにアクセスします。
また、TCPIPのプロトコルスタックはLwIP(Lightweight IP)やuIPといったオープンソースが使われる事が多いようです。

ライセンス

公式サイトで「 Apache 2.0 OR GPL 2.0-or-later license」と記されており、デュアルライセンスとなっています。つまり、Apache 2.0とするかGPL2.0以降とするかをユーザーが選択可能になっています。

入手方法

GitHubのリポジトリがあるので、ここから入手します。
また、マイコンメーカによっては評価ボードのサンプル用にポーティングされたものがあったりするので、使えそうなサンプルがないかを探してみるのもいいかもしれません。

mbedTLSのコンフィギュレーション

mbedTLSにはコンフィギュレーション用のヘッダファイルや、他のミドルウェアとやり取りするためのラッパーファイルが用意されているので、これらを修正して使用します。

コンフィギュレーション用のヘッダファイルの作成

mbedTLS自体の設定を行うコンフィギュレーションファイルを設定します。
mbedTLSのver3.0以降は「mbedtld_config.h」、ver3.0より前のバージョンの場合は「config.h」というファイルが用意されています。リポジトリの下記の場所にありますので、これを編集していきます。

上記のリンクは、例としてver3.6.0とver2.28.8のものを示しました。必要に応じて使用するバージョンのものを参考にしてください。

乱数発生器の使用設定

乱数発生器による乱数取得を行う場合は、「mbedtld_config.h」もしくは「config.h」に下記の定義をするようにしてください。(デフォルトではコメント化されているようなので定義するよう修正してください)

#define MBEDTLS_ENTROPY_HARDWARE_ALT

このマクロを定義することにより、乱数生成の際にはユーザーが定義した「mbedtls_hardware_poll()」を呼び出すようになります。この関数の仕様は下記のようになります。関数の内部で乱数生成を行い、引数の「output」に格納するように実装してください。

int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen );
項目1 項目2 説明
機能 乱数生成を行う際に呼ばれる関数
引数 data
output 生成した乱数を格納する配列のポインタ
len outputの指す配列に格納したい要素数
*olen 実際にoutputに格納した配列の要素数
返り値 0が正常値。それ以外はエラーとして判断

また、この関数では生成した乱数をunsigned char型の配列に格納するため、「*olen」に設定する値もunsigned char型の配列に格納した数を設定する必要があります。

その他のコンフィグファイルの設定

「mbedtld_config.h」もしくは「config.h」で設定するマクロの一部をここに示します。

マクロ名 説明
MBEDTLS_HAVE_TIME_DATE なし time.hの日付取得関数を使用する際に定義
MBEDTLS_HAVE_TIME なし time.hの時刻取得関数を使用する際に定義
MBEDTLS_CIPHER_MODE~ なし 「~」に入る暗号方式を使用する際に定義
MBEDTLS_CIPHER_PADDING_~ なし 「~」に入る暗号方式で\nパディングモードを使用する際に定義
MBEDTLS_REMOVE_~ なし 「~」に入る暗号方式を無効化する際に定義
MBEDTLS_ECP_~_ENABLED なし 「~」に入る楕円曲線暗号(ECC)のモジュールを有効化する際に定義。公開鍵暗号で使用
MBEDTLS_ECDSA_DETERMINISTIC なし RFC 6979にて示す、秘密鍵とメッセージから乱数生成し、デジタル署名を検証するECDSA(決定論的署名)を有効化する際に定義
MBEDTLS_KEY_EXCHANGE_~_ENABLED なし 「~」に入る鍵交換時の暗号方式を有効化する際に定義
MBEDTLS_ERROR_STRERROR_DUMMY なし ダミーのエラー関数を有効化する際に定義
MBEDTLS_GENPRIME なし 素数生成コードを有効化する際に定義。MBEDTLS_BIGNUM_Cも定義して使用する
MBEDTLS_FS_IO なし ファイルシステムを有効化する際に定義
MBEDTLS_PK_RSA_ALT_SUPPORT なし HSMなどの外部セキュリティモジュールから生成したRSAの鍵を有効化する際に定義
MBEDTLS_PKCS1_~ なし 「~」に入るバージョン番号のPKCS(公開鍵暗号標準)を使用する際に定義
MBEDTLS_SSL_ALL_ALERT_MESSAGES なし エラー発生時にRFCに則ったエラーメッセージ送信をするに定義。無効化することで攻撃者に情報を与えないため、定義したほうが絶対に良いわけではない
MBEDTLS_SSL_ENCRYPT_THEN_MAC なし RFC7366のEncrypt-then-MACのサポートを有効にする際に定義。Encrypt-then-MACは共通鍵暗号とメッセージ認証コードを組み合わせる際の方式を示す
MBEDTLS_SSL_EXTENDED_MASTER_SECRET なし RFC7627に示されているハンドシェイク中の攻撃に対応するための処理を行う際に定義
MBEDTLS_SSL_FALLBACK_SCSV なし SSLへのダウングレード攻撃(POODLE)への対応を行う際に定義
MBEDTLS_SSL_RENEGOTIATION なし TLS際ネゴシエーションに対応する際に定義。鍵のリフレッシュ時に使用される
MBEDTLS_SSL_MAX_FRAGMENT_LENGTH なし RFC6066の最大フラグメントサイズ設定に対応する際に定義
MBEDTLS_SSL_PROTO_TLS~ なし 「~」に入るバージョンのTLSに対応する際に定義
MBEDTLS_SSL_PROTO_DTLS なし DTLSに対応する際に定義
MBEDTLS_SSL_ALPN なし RFC7301で示されている、ハンドシェイクにアプリケーション層のやり取りを追加する際に定義
MBEDTLS_SSL_DTLS_~ なし 「~」に示す機能をDTLSでサポートする際に定義
MBEDTLS_SSL_SESSION_TICKETS なし RFC5077に示すセッションチケット機能を使用する際に定義
MBEDTLS_SSL_SERVER_NAME_INDICATION なし RFC6066に示す、一つのIPアドレスに複数のドメイン名の指定を可能にする際に定義
MBEDTLS_VERSION_FEATURES なし コンパイル時に有効化した機能を確認できるようにする際に定義
MBEDTLS_X509_RSASSA_PSS_SUPPORT なし X.509の証明書の検証と解析機能を使用する際に定義
MBEDTLS_~_C なし 「~」に入る機能をモジュール全体としてサポートする際に定義。使用しないモジュールをコメント化することによってファームウェアサイズやメモリの使用量を減らす
MBEDTLS_NO_UDBL_DIVISION なし 整数の除算結果の正確性を上げる機能を使用する際に定義。有効化することで除算に使うメモリが増えるので注意
MBEDTLS_AES_ROM_TABLES なし 事前にROMに保存されたAES用のテーブルを使用する際に定義
MBEDTLS_NO_PLATFORM_ENTROPY なし 乱数生成時にデフォルトで用意されているモジュールを呼び出さない際に定義。ハードの乱数生成器を使用する際は定義した状態とする
MBEDTLS_ECP_MAX_BITS ~512 デフォルトでは521ビットの楕円曲線をサポートするため、512が設定されている。この値よりも小さくしてもよいが、メモリ使用量に与える影響は少ない
MBEDTLS_MPI_MAX_SIZE ~1024 整数を表現するのに使用する最大バイト数。デフォルトは1024だが、必要に応じて小さくしても問題ない
MBEDTLS_ECP_WINDOW_SIZE 2~6 楕円曲線の計算で使用するテーブルサイズ。増やすことでメモリ使用量も上がる

割愛しましたが、「mbedtld_config.h」もしくは「config.h」には他にも設定可能な項目があるので、興味がありましたら下記を参照してください。

TCPIPのプロトコルスタックとのコンフィギュレーション

mbedTLSは、BSDソケットAPIを前提としたネットワークの抽象レイヤがあります。
図に示すと下記のような構成となっています。

mbedTLS構成図.png

暗号化・復号化したデータの受け渡し先のAPIの定義のみが決まっている状態です。使用するプロトコルスタックが違う可能性があるので、関数の実装はユーザーが行います。

ソースコードは「net_sockets.c」に定義します。

「net_sockets.c」に実装が必要な関数

ユーザーが「net_socket.c」に実装する必要があるのは下記の関数です。下記の関数を、使用するTCPIPのプロトコルスタックのAPI等を用いて実装する必要があります。

void mbedtls_net_init(mbedtls_net_context *ctx)
項目1 項目2 説明
実装する機能 TCP/IPのプロトコルスタックとソケット通信の初期化
引数 ctx ソケットのファイルディスクリプタを保持しておくための構造体
int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto)
項目1 項目2 説明
実装する機能 引数で指定したhostとportのソケットに接続する。クライアント用関数
引数 ctx ソケットのファイルディスクリプタを保持している構造体
host 接続相手のソケットのホスト名
port 接続相手のソケットのポート番号
proto 使用するプロトコル。MBEDTLS_NET_PROTO_TCPかMBEDTLS_NET_PROTO_UDPを入れる
返り値 正常終了時は0。エラー発生時はMBEDTLS_ERR_NET_SOCKET_FAILED, MBEDTLS_ERR_NET_UNKNOWN_HOST, MBEDTLS_ERR_NET_CONNECT_FAILEDのどれかを返すようにする

|

int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)
項目1 項目2 説明
実装する機能 引数で指定したIPアドレスとportをソケットに紐づける。TCPの通信をする場合はソケットをリッスン状態にしておく。サーバー用関数
引数 ctx ソケットのファイルディスクリプタを保持している構造体
bind_ip ソケットに紐づけるIPアドレス
port ソケットに紐づけるポート番号
proto 使用するプロトコル。MBEDTLS_NET_PROTO_TCPかMBEDTLS_NET_PROTO_UDPを入れる
返り値 正常終了時は0。エラー発生時はMBEDTLS_ERR_NET_SOCKET_FAILED, MBEDTLS_ERR_NET_BIND_FAILED, MBEDTLS_ERR_NET_LISTEN_FAILEDのどれかを返すようにする

|

int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *cip_len)
項目1 項目2 説明
実装する機能 接続要求を許可する。サーバー用関数
引数 bind_ctx 接続を受け付けるソケット情報。ユーザが指定
client_ctx 接続要求を送ってきたソケット情報。関数内で設定される
client_ip 接続要求を送ってきたソケットのIPアドレスを格納する配列のポインタ
buf_size client_ipが指すバッファのサイズ。ユーザが指定
cip_len client_ipに書き込まれているIPアドレスのデータサイズ。関数内で設定される
返り値 正常終了時は0。エラー発生時MBEDTLS_ERR_NET_ACCEPT_FAILED, MBEDTLS_ERR_NET_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_WANT_READのどれかを返すようにする

|

int mbedtls_net_set_block(mbedtls_net_context *ctx)
項目1 項目2 説明
実装する機能 ソケットをブロッキングモードに設定する。(指定されたデータが送受信完了するまで、ライブラリの送受信関数から返ってこないようにする)
引数 ctx ソケットのファイルディスクリプタを保持している構造体
返り値 正常終了時は0。エラー発生時は0以外をかえすようにする
int mbedtls_net_set_nonblock(mbedtls_net_context *ctx)
項目1 項目2 説明
実装する機能 ソケットをノンブロッキングモードに設定する。
(指定されたデータの送受信完了を待たずに、ライブラリの送受信関数が終了する)
引数 ctx ソケットのファイルディスクリプタを保持している構造体
返り値 正常終了時は0。エラー発生時は0以外をかえすようにする
void mbedtls_net_usleep(unsigned long usec)
項目1 項目2 説明
実装する機能 usecで指定した時間(単位はms)、呼び出し先のスレッドをスリープする。
引数 usec 待つ時間。ms単位で指定
int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
項目1 項目2 説明
実装する機能 データを受信する
引数 ctx ソケットのファイルディスクリプタを保持している構造体
buf 受信したデータを入れるバッファのポインタ
len 受信できるデータのサイズ
返り値 ブロッキングモードでは受信したbyte数を返す。ノンブロッキングモードではMBEDTLS_ERR_SSL_WANT_READを正常値として返す。何らかのエラー時はどちらのモードでも負の値のエラーコードを返す。
int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
項目1 項目2 説明
実装する機能 データを送信する
引数 ctx ソケットのファイルディスクリプタを保持している構造体
buf 送信するデータを入れたバッファのポインタ
len 送信データのサイズ
返り値 ブロッキングモードでは送信したbyte数を返す。ノンブロッキングモードでMBEDTLS_ERR_SSL_WANT_WRITEを正常値として返す。何らかのエラー時はどちらのモードでも負の値のエラーコードを返す。
int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout)
項目1 項目2 説明
実装する機能 データを受信する。timeoutで指定した時間受信データがなければ受信街を終了してリターンする
引数 ctx ソケットのファイルディスクリプタを保持している構造体
buf 受信したデータを入れるバッファのポインタ
len 受信できるデータのサイズ
timeout タイムアウト時間(ms)
返り値 タイムアウト時はMBEDTLS_ERR_SSL_TIMEOUTを返す。主にブロッキングモードのソケットで使用
void mbedtls_net_free(mbedtls_net_context *ctx)
項目1 項目2 説明
実装する機能 引数で指定したソケットを解放する
引数 ctx ソケットのファイルディスクリプタを保持している構造体
void mbedtls_net_close(mbedtls_net_context *ctx)
項目1 項目2 説明
実装する機能 引数で指定したソケットをクローズする
引数 ctx ソケットのファイルディスクリプタを保持している構造体
int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
項目1 項目2 説明
実装する機能 第一引数のctxが示すコンテクストに送受信が可能なソケットがあるかを調べる。BSDのソケットAPIのselect()に該当する機能の使用が推奨
引数 ctx ソケットのファイルディスクリプタを保持している構造体
rw
timeout タイムアウト時間(ms)
返り値 正常終了時もしくはタイムアウト時は、読み出し可能ならMBEDTLS_NET_POLL_READを、書き込み可能ならMBEDTLS_NET_POLL_WRITEを返す。どちらも可能ならこの二つの論理和を返す。エラー発生時は負の値をかえすようにする

また、net_socket.cの実装は、LwIPなどよく使われるオープンソースの場合は実装例があることも多いです。評価ボードのサンプルプロジェクトとしてSSL/TLSのサンプルがある場合はそれを参考にしながら実装してもいいかもしれません。

ビルド

MakeやCMakeを使用してのビルド方法に関して下記の公式サイトで記されています。
https://mbed-tls.readthedocs.io/en/latest/getting_started/building/

このあたりの詳細は追って調査後に追記しようかと思います。

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?