mbedTLSの組込で分かったこと

実際に組込TLSをやってみて分かったことのまとめ。公開しているのはこれ、TlsTcpClient

これは実際の端末でTLS 1.2で通信しているシーケンス。Application Dataが暗号化されている。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-19-14-42-04

対象はParticleというデバイス。CPUはCoretex ARM M3 120MHz、1MB flash, 128KB RAMになっている。1Mbyte Flashだけどシステム用に512Kやら色々と使われて、ユーザアプリ領域には128Kbyte利用できる。

ここにTLS(TCP)をサクッと入れて利用できるlibraryを提供しようという試みになる。ParticleではTCPClientという物が用意されていて、このTLS版=TlsTcpClientということになる。

ちなみにMQTT libraryをこの端末向けに提供していて、今まで3500以上ものビルド&アプリで利用されていたり、まぁ、それなりには使われている。ここでMQTT TLSに対応してよ!!というリクエストを受けていたけど、面倒くさいから放置していた。自分は約10年近く昔にTLS libを直接使ったOverlay Networkを作った経験上、TLSは鬼門(ゲロむずい)というのを知っていたから、まぁ、そのうち本家で対応するだろう…と。けど、ずーっと待っていても対応されない。何故かDTLSはfirmwareからビルドすれば使えるようだけど、肝心のWebIDEやサクッと使える環境がない。という事で、突然思い立って実装して既にpublicとして使えるようにした。

そこで分かった組込TLSのポイントを少しまとめ。

組込TLS実装上のポイント

■ OpenSSL使いたい!!
はい、SSLと言えばOpenSSL最強です。大抵の端末、サーバに入っていて、SSLSocketという素晴らしいものが使える。ただ、当然だけどサイズが半端ない。現時点で最新のopenssl-1.1.0c.tar.gzをUbuntu x64でビルドした時のlibサイズの総量は、9227602byteもあった。どんなに削ったとしても128Kbyteには程遠い。
そこで組込向けopen sourceなTLSには以下の種類がある。

wolfTLS(CyaSSL)
mbedTLS(polrSSL)
axTLS
matrixSSL

他にも色々とある。この中からチョイスしたのはmbedTLS。考慮したのはライセンス、将来性の2つ。
もちろんだけど、同じmbed、ARMの石だからといってlibを持ってきてビルドすればOK!!みたいな事は全くない…このParticleの環境上で動くように対応する事になる。主に行うのは次の2点。この修正作業に2日くらい費やした。

1. コンパイルエラーが超膨大に出てくるから、それをいちいち修正、解消
2. 必要なlibc関係の関数がParticle上の環境に無い。関数を作って追加したりして補完。

■ CPUパワー
よくTLSをこういう貧弱なMCU/CPUの石でやろうとすると言われるのが、CPU遅いからTLSで通信とか使えないんじゃない?というもの。ただ、TLSをCortext M3とかでやると重くてヤバイとかは幻想だった。Cipher SuiteがTLS_RSA_AES128_GCM_SHA256のケースでネットワーク時間(RTT、ここでは上流にiPhone LTEをテザリングしてパケットキャプチャした)を入れても、上画像のWireSharkキャプチャの通り20ms以下でHandshakeが収まる。
M3 120Mhzいいね。AES128も高速に処理出来ていて素晴らしい。

ただ、最近のこの手のモノではアクセラレータが積んである。例えばESP32 ( ESP32:IoTボード ESP8266のお兄さん ) はこのサイズでRSA/AES/SHAのアクセラレータが搭載されていて、そもそも的にここまで実装する必要すらない。
恐らく今後は暗号化/セキュリティの実装がこの手の組込物には搭載されて、ここまで気合で実装する必要はなく、より高速、簡単に使えるようになると思われる。

■ サイズ調整
これが恐らく一番のポイントになる。容量と採用するCipher Suitesとかオプション&アルゴリズムのバランスがサイズに対して絶妙に効いてくる。コレ、マジ重要。
TLSはザックリだと、「通信相手と利用可能な暗号化の調整(ネゴシエーション)を行って、通信で利用される鍵交換を安全に行ったセッションを確立して通信を行う」といった感じの物で、対応している暗号化のアルゴリズムが多い方が”気持ちとして”なんとなく嬉しい。この辺はTLSやPKI周辺への多少のノウハウが必要だったり、何というか…組込や通信だけじゃなく非常に広範な技術への俯瞰した部分が必要になると思われ。
つまり、色々とアルゴリズムは入れたい、ただ入れると容量オーバーでfirmwareに入れられないと言う葛藤になる。
現時点ではこんな感じ。

webide-build

アプリケーションのビルドとTLS部分のビルドも入れて92Kbyte、本体だけだと80Kbyteくらい。ちなみに商用物だと50Kbyteくらいのが普通っぽい。もう少し調整すればTLS部分だけで商用並の50〜60Kbyteまで綺麗にできる自信はある。今は1stバージョンだから…という言い訳(ということで)。対応するCipher Suiteはこちら。

TLS_DHE_PSK_WITH_AES_256_CBC_SHA
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
TLS_DHE_PSK_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_PSK_WITH_AES_256_CBC_SHA
TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
TLS_RSA_PSK_WITH_AES_128_CBC_SHA
TLS_PSK_WITH_AES_256_CBC_SHA
TLS_PSK_WITH_AES_128_GCM_SHA256
TLS_PSK_WITH_AES_128_CBC_SHA256
TLS_PSK_WITH_AES_128_CBC_SHA

現時点から将来的に安全で高速に処理が出来るだろう暗号化、殆どのサーバ側で対応しているだろうアルゴリズムを対象にしている。ごっそりと削ったのが、TLSサーバとしての処理部分、DTLSとして利用される部分、何気に効いたのがアルゴリズムよりも、debug部分やデフォで使われてしまうtest certificationだったりもする。

■ 全体感
何となく思い立ってやり始めて、ソースコードの調整と全体感の理解に2日、ユーザーが利用するクラスと実際の実装に1日のトータル3日くらいで作ってpublish。ずっとリクエストされていたから、とっとと作れば良かったのに感はあるけど、何にしてもTLSは鬼門でネットワーク、セキュリティ、アルゴリズム、現時点での動向とか、ノウハウが非常に広範な部分への俯瞰した部分が必要になるし、実装もゲロ難しいから「必要だったら自分で実装してプルリク送ってよ」的に避けていた…mbedTLSのお手軽さにかなり助けられた。

mbedTLS の作りの思想、構造が大体理解出来た感はある。多分、大抵の環境で対応可能な気がする。
IoT的な環境ではTLSを始めとした暗号化は間違いなく必要、重要になる。これから、mbedTLSを使ったりする方へは、全体構造とか資料で見つけるより、コードを読んだ方が早いと思う。日本語の資料なんてググってもろくに無いけど、構造自体はそれほど難しくない。それ以上に容量調整や使うアルゴリズムをどうするか?とか、利用環境上で使えない(存在しない…orz)関数を用意するといった部分がより多く必要になる。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です