1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

蟹さんのBare MetalでBearSSL

Last updated at Posted at 2018-03-23

IoTといえどもインターネットにつなぐのであれば、SSL(TLS)は必須な時代になったので、蟹さんもSSLを話せるようにしてみました。

前にも書きましたがaxTLSがいまいちだったので調べていたらBearSSLという新しい実装が見つかり、これをポートする事にしました。

SSL通信はTCP通信の中を通すように作られています。

SSL.png

BearSSLはもちろんCで書かれたライブラリなのですが、独自のプリプロセッサーを使ってCコードを生成している部分もあります。プリプロセッサーはCSで書かれていて、Windowsのバイナリのみの提供になります。

BearSSLはシステム依存が時間と乱数しか無くEmbedな環境にも非常に優しく出来ています。axTLSではソケットのread/writeがハードコードされてしまっていますが、BearSSLでは関数渡しで自前のコードが使えるようになっています。

乱数はもともとUNIX用とWindows用のコードが用意されているのですが、Embedでは使えないのでMT19937のコードを入れてみました。

時間はtime()関数が必要なのですが、BearSSLと自前のコードで読み込むヘッダーが違っていてtime_tが4バイトと8バイトになってしまい、X509の時間のチェックがうまくできなくてちょっとはまりました。

BearSSLのサンプルのクライアントコードをベースにlwIPのRAW TCPコードと融合させてどうにか動くようになりました。

BearSSL.png

入力処理の流れは以下のようになっています。

Etherパケット受信割り込み -> low_level_input() -> データをnetif.input()に渡す -> lwIPが処理 -> tcp_recv()で設定した関数が呼ばれる -> 受信データをローカルバッファに保存 --- BearSSLに設定したread関数でバッファデータを引き渡し -> ネゴシエーションなどはBearSSL内で処理され通信内容はbr_sslio_read()で読める

出力はリニアに処理されます。

br_sslio_write_all()で書く -> BearSSLが処理 -> BearSSLに設定したwrite関数 -> lwIP -> lwIPに設定したoutput関数でデバイスリングバッファに保存

スクリーンショット(2018-03-23 12.55.10).png

tcpdumpでの通信内容

microserver % sudo tcpdump -i re0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on re0, link-type EN10MB (Ethernet), capture size 65535 bytes
09:54:04.457395 ARP, Request who-has 10.10.10.2 tell 10.10.10.2, length 46
09:54:04.457494 ARP, Request who-has 10.10.10.3 tell 10.10.10.2, length 46
09:54:04.457503 ARP, Reply 10.10.10.3 is-at 00:13:3b:12:81:04 (oui Unknown), len
gth 28
09:54:04.467366 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [S], seq 6509, win 
2144, options [mss 536], length 0
09:54:04.467410 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [S.], seq 100541135
4, ack 6510, win 65535, options [mss 536], length 0
09:54:04.477530 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [P.], seq 1:194, ac
k 1, win 2144, length 193
09:54:04.495526 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], seq 1:537, ack
 194, win 65535, length 536
09:54:04.495541 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], seq 537:1073, 
ack 194, win 65535, length 536
09:54:04.495548 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], seq 1073:1609,
 ack 194, win 65535, length 536
09:54:04.495554 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 1609:2060
, ack 194, win 65535, length 451
09:54:04.497594 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 537, win 2
144, length 0
09:54:04.497731 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 1073, win 
2144, length 0
09:54:04.749933 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], seq 1073:1609,
 ack 194, win 65535, length 536
09:54:04.757573 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 1609, win 
2144, length 0
09:54:04.757621 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 1609:2060
, ack 194, win 65535, length 451
09:54:04.757756 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 2060, win 
1693, length 0
09:54:04.767515 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 2060, win 
1693, length 0
09:54:05.236710 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [P.], seq 194:236, 
ack 2060, win 1693, length 42
09:54:05.337974 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], ack 236, win 6
5535, length 0
09:54:05.347562 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [P.], seq 236:279, 
ack 2060, win 1693, length 43
09:54:05.347944 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 2060:2066
, ack 279, win 65535, length 6
09:54:05.643961 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 2060:2103
, ack 279, win 65535, length 43
09:54:05.647583 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 2103, win 
1650, length 0
09:54:05.649108 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [P.], seq 279:335, 
ack 2103, win 1650, length 56
09:54:05.649297 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 2103:2275
, ack 335, win 65535, length 172
09:54:05.657611 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 2275, win 
2144, length 0
09:54:05.657659 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [P.], seq 2275:2298
, ack 335, win 65535, length 23
09:54:05.701507 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [P.], seq 335:358, 
ack 2298, win 2121, length 23
09:54:05.701553 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [F.], seq 358, ack 
2298, win 2121, length 0
09:54:05.701583 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [.], ack 359, win 6
5535, length 0
09:54:05.701716 IP 10.10.10.3.8080 > 10.10.10.2.49153: Flags [F.], seq 2298, ack
 359, win 65535, length 0
09:54:05.707641 IP 10.10.10.2.49153 > 10.10.10.3.8080: Flags [.], ack 2299, win 
2120, length 0

09:54:05.647583までがネゴシエーションでこれ以降が実際の通信になります。

もちろんmrubyから使えるようにするつもりですが、インターフェースはなにか有り物に似せて作ろうかとも思っています。

ポートして分かった事はCA(TA)をどう管理するかとある程度正確な時間が必要という事です。サンプルプログラムではTAをハードコードしてありますが、そのTAで認証できない証明書がサーバに貼られた場合はエラーになりますし、ある程度の柔軟性を持った仕組みが必要な気がします。時間についてはRTCをつむしかないかもしれませんね。

サーバー側が自分の管理下でオレオレ証明書で運用するのであればTAは固定でもよいかもしれないが、一般のサービスに接続する場合は証明書の発行元が変わる事も考えられTAの管理は柔軟にしなければいけない。

BearSSLって本当に素晴らしいです。

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?