ESP32-S and Arduino

kaduhiさんからESP32-Sを米国から頂いて…中国〜米国〜そして日本へ遠路はるばるようこそ。ありがとうございます!!感謝です、実験&コードを作ったり遊んでみます。

p_20161121_213054_hdr

ESP32のスペックはざっくりだと。詳細はググると出てくるけど、本家のはこちら
CPU : Xtensa® 32-bit LX6 Dua-core processor
ROM/SRAM: 448 KByte ROM, 520 KByte SRAM
WiFi : 802.11 b/g/n/e/i
Bluetooth : Bluetooth v4.2 BR/EDR and BLE
他には、RTC、そして自分的に凄いと思うのが、ハードウェア暗号化アクセラレーション。TLSが(実装すれば)サクッとつかえるー!!AES-HASH(SHA-2) library-RSA-ECC-Random Number Generator。凄い、これ凄い。言ってしまえばNWにつながる小さいPCっすね。

手持ちの歴代ESPとのサイズ比較な感じだと。右下がESP32-S、左上がESP-WROOM-02、右上はESP8266、左下がESP12。
p_20161121_220216

基板に付けるとこんな感じに。
p_20161121_224414

img_0083

開封して基板にとりあえず付けるとこんな感じ。前のESP8266に比べて圧倒的にピン数が多いっすね。「これだけのだし、何でも面白いものを作れるだろ?」という暗黙のプレッシャーを感じるです…

ここで、この子にピンヘッダをおもむろに付けようと思ったけど、2列だからブレッドボードに指したりしようとすると何かと不都合が…
そういう時に活躍するのが、スルホール用テストワイヤとか。ただ、自分は後でピンの抜き差しを自由に出来るように、2列10ピンのピンソケットの1個を抜いて使うことに。

img_0086

完成

img_0095

Arduinoで使ってみる

すでにESP32 Arduinoが公開されている。ESP8266と一緒な感じでArduino IDEから使えると非常に便利で、開発者も一気に広まるというのもあるからね。ということで、このgitを使う。

記載の通り進める。自分の環境はMacOS 10.11.6でPythonは2.7というのもあって、pyserialを入れる必要があった。

cd /Applications/Arduino.app/Contents/Java
cd hardware
mkdir espressif
cd espressif
git clone https://github.com/espressif/arduino-esp32.git esp32
cd esp32/tools
python get.py
# pyserialを入れる。pyenvとかpipを使っている場合は、それに合わせて入れる
wget https://pypi.python.org/packages/1f/3b/ee6f354bcb1e28a7cd735be98f39ecf80554948284b41e9f7965951befa6/pyserial-3.2.1.tar.gz
tar -zxvf pyserial-3.2.1.tar.gz
cd pyserial-3.2.1
sudo python setup.py install 

次にArduinoの起動〜利用。Arduinoを起動してESP32を選択。
%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-24-1-37-13

次にESPとシリアルの結線。これはそのまんま。自分はFT232RL搭載小型USB-シリアルアダプタ 3.3Vをいつも使っているんだけど、3.3V/GND, TX<->RXをESP32側とつなげるとOK。

起動時のログはこんな感じでシリアルから見れる(既にArduino化されているのだけど)。
%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-24-1-22-31

そして問題の書き込み。これはムチャクチャ簡単。

1. RESET + IO0を同時押し
2. RESETを離す
3. Arduino IDE上からFlashをポチる

以上な感じ。この辺はムチャクチャ簡単に出来る。2の時点でシリアルを見るとこんな感じの表記が出ている。

%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-24-1-24-15

そして書き込みをすると、Arduino IDEではこんな表記が出る。

%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-24-1-24-21

そしてLEDピカー

img_0093

上向きにピンソケットを出せば良かったかな…と2秒くらい後悔したw FT232RLだけでサクサクっと動かして使えるのはめっちゃ良い。

あと不明な所はESP32 forumを見れば解決すると思われ。最後に、FCCは通っているけど現時点ではTELECは通って無いっすね。WiFiのlibとかは上記のgitに普通に入っている。ここではWiFiを出しているとは何も書いていないんでお察しでw

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)関数を用意するといった部分がより多く必要になる。

TLS client library for Particle Photon

TlsTcpClient for Particle Photn, Now release version 0.1.0.

TLS TCP client library cloud not use on Particle Photon WebIDE, but NOW we can use TLS TCP simple client library based by mbedTLS. Here is sample source code. Developer can connect to every TLS web/server using that Root CA pem file.

#include "application.h"

#include "TlsTcpClient/TlsTcpClient.h"

// Photon connect Let's Encrypt Website in this example.
#define LET_ENCRYPT_CA_PEM                                              \
"-----BEGIN CERTIFICATE----- \r\n"                                      \
"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\r\n"  \
"-----END CERTIFICATE----- \r\n"
const char letencryptCaPem[] = LET_ENCRYPT_CA_PEM;

void setup() {
    Serial.begin(9600);
}

void loop() {
    unsigned char buff[256];

    TlsTcpClient client;

    // setup Root CA pem.
    client.init(letencryptCaPem, sizeof(letencryptCaPem));
    
    // connect HTTPS server.
    client.connect("www.hirotakaster.com", 443);
    
    // send to HTTPS request.
    int len = sprintf((char *)buff, "GET /robots.txt HTTP/1.0\r\nHost: www.hirotakaster.com\r\nContent-Length: 0\r\n\r\n");
    client.write(buff, len );

    // GET HTTPS request.
    memset(buff, 0, sizeof(buff));
    while(1) {
        if (!client.available()) {
            delay(100);
        } else {
            int ret = client.read(buff, sizeof(buff) - 1);
            if (ret > 0) {
                Serial.println((char *)buff);
                break;
            }
        }
    };
    delay(5000);
}

This library already add to Particle WebIDE contribute library, it can use very easy.
%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-16-21-18-10

This is my web server(this blog) and Photon TLS sequence and cipher spec captured with Wireshark. Cipher suites are AES128/256 based.
%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-16-21-00-33