SDKは1.3.0 (Release date: Aug 08, 2015)を使用しています。
ドキュメントも、これ(esp_iot_sdk_v1.3.0_15_08_08.zip)に含まれている2C-ESP8266__SDK__Programming Guide__EN_v1.3.0.pdfを参照しました。
現状
8/28現在、Arduino core for ESP8266はSSL(TLS)でのclientに対応していない。対応して欲しいという要望&対応したいねという話は出ている。
ESP8266のSDKとしては、SSLに対応している。
※ただし、制約あり(この下に書きます)
処理の流れ
公式によるサンプルコードがEspressifのフォーラムにあるので、それを見るとだいたい分かります。以下も非常に参考になります。
DSAS開発者の部屋:ESP8266 モジュールの AT コマンドに SSL クライアント機能を追加する
ESP-WROOM-02で、IFTTTをhttps(SSL/TLS)で呼び出す例 - Qiita
大雑把な流れとしては...
//証明書ストアを用意 unsigned char *default_certificate; unsigned int default_certificate_len = 0; unsigned char *default_private_key; unsigned int default_private_key_len = 0; //espconn, _esp_tcpを定義 LOCAL struct espconn user_tcp_conn; LOCAL struct _esp_tcp user_tcp; //接続先のIPアドレスとポートを設定 user_tcp.remote_ip[0] = 192; user_tcp.remote_ip[1] = 168; user_tcp.remote_ip[2] = 1; user_tcp.remote_ip[3] = 128; user_tcp.remote_port = 443; //自分のポートを設定 user_tcp.local_port = espconn_port(); //type, state等を設定 user_tcp_conn.proto.tcp = &user_tcp; user_tcp_conn.type = ESPCONN_TCP; user_tcp_conn.state = ESPCONN_NONE; //接続時、再接続時、接続断時のコールバックを設定 espconn_regist_connectcb(&user_tcp_conn, user_tcp_connect_cb); espconn_regist_reconcb(&user_tcp_conn, user_tcp_recon_cb); espconn_regist_disconcb(&user_tcp_conn, user_tcp_discon_cb); //SSLバッファサイズを設定 espconn_secure_set_size(ESPCONN_CLIENT,5120); //接続する espconn_secure_connect(&user_tcp_conn);
みたいな感じ?
user_tcp_connect_cb()関数の中でデータ送受信時のコールバックを設定してあげれば良いみたい。
void user_tcp_connect_cb() { espconn_regist_recvcb(pespconn, user_tcp_recv_cb); espconn_regist_sentcb(pespconn, user_tcp_sent_cb); }
サーバからの応答は
void user_tcp_recv_cb(void *arg, char *pusrdata, unsigned short length)
のpusrdataに入ってくるので、これを出力するなり判定するなりすると良い。
SSLバッファサイズはデフォルト(espconn_secure_set_sizeを呼ばない場合)で2048バイトになっているので、SSLパケットが2048バイトを超えそうな時は適宜増やしてね、ということらしい。
最大8192バイトらしいけど、8192を設定したらメモリに乗り切れないっぽくて(確保できない?)、espconn_secure_connectの段階でこけました。
公式サンプルコードにあるように5120くらいが限界かな...?
使用できるプロトコル(バージョン)と暗号
たぶん、ここが一番重要で、メモリ周りとかは全然大丈夫だけどespconn_secure_connectした直後にuser_tcp_discon_cbが呼ばれる(接続断される)ような、とあるサービスのAPIサーバがあって、Wiresharkでパケットキャプチャしたら原因が分かりました。こちらがESP8266からサーバに送信されたClient Hello。
バージョンはTLS 1.1で、Cipher Suitesは以下の4種。
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_RC4_128_SHA
- TLS_RSA_WITH_RC4_128_MD5
TLS 1.1を拒否ってたり、上記暗号種での接続を拒否ってると
「お前の指定したバージョン、暗号種ではうちに繋げねーぞ」とHandshake Failureが返ってきてServer Helloしてくれない訳です。
HeartbleedとかPOODLEとか色々あった関係で、厳しめなところは繋がらないという感じかなぁ。
このマイコンの性能上、強度の高い暗号アルゴリズムは載せられないのでしょうが、IoT向けを前面に押し出してるからには、もうちょっと頑張ってほしい...
追記:その後、Arduino core for ESP8266でWiFiClientSecureが追加され、httpsが叩けるようになりました。