0
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?

STM32マイコンからサーバへ画像をセキュア転送する

Last updated at Posted at 2025-03-06

はじめに

普段からよく使っているSTM32マイコンを使って、
SSL/TLSライブラリを使った実験用ソースコードを製作した。
自宅に設置している家電操作用ラズパイサーバや、
そのサーバにデータ送信するクライアント端末は全て平文でデータ受け渡しをしている。

今回、wolfSSLライブラリを使った画像アップロードデモを行い、
自宅のドアフォンに移った訪問客を外出先から確認する開発に繋げたい

準備物

●NUCLEO-F446ZE × 1
●MM-FT232H × 1 ※UART-USB変換可能なデバイスであれば何でもOK

上記2台をUART通信で接続します。接続関係は、
■ PD6(NUCLEO-F446ZE)↔ADBUS0(MM-FT232H)
■ PD5(NUCLEO-F446ZE)↔ADBUS1(MM-FT232H)
互いのGNDを接続 ←これを忘れると2日溶かします

筆者はArduino拡張基板を使って2台を接続しました。
Nucleo基板上のピンソケットは左右それぞれ2列ありますが、
上記端子PD5,6は左側ピンソケットの内側にあります。
拡張基板をそのまま内側に接続すると右側ピンソケットが1列はみ出すので、
はみ出た1列分を右側ピンソケット外側に無理やり曲げて装着します。

IMG_3978.JPG

ネットワーク構成図

概ね、ハードウェアのセッティングが完了しました。
ネットワーク構成はあくまで参考ですので、等価な接続構成になっていればOKです。

ソースコード

以下にサンプルプログラムから機能追加/修正内容をまとめた。

●(server-tls-uart.c):
・【追加】base64エンコード/デコード関数を追加
・【追加】base64デコードした画像データを*.jpgファイルにする機能を追加
・【修正】examplesのファイル階層変更により、秘密鍵とサーバ証明書の相対パスが変わっていたので修正
・【修正】クライアントから受け取るデータの受信データバッファサイズを拡張
・【修正】ファイル名を「server-tls-uart.c」から「server-tls-uart-picture.c」に変更

●(wolfssl_example_ex.c)
・【追加】デモメニュー画面でのコマンド受付時間を0.1sから1sに変更
・【追加】実行するデモ機能を'l','m','s'に拡張し、ヘッダファイルに置いた画像データを選択

●(main.c)
・【追加】既存のデモ関数(wolfCryptDemo)と新規デモ関数(wolfCryptDemo_ex)をマクロ切替え

●(base64_encoder.bat)
・【追加】ドラッグ&ドロップした画像ファイルをbase64エンコードして、ヘッダファイルを出力

●(default_conf.ftl) ※wolfSSLから提供されているST用ファームウェアパッケージ
・【追加】Hardware platformとしてSTM32F446xxを追加
→STM32CubeMXからコード生成すると、自動で上書きする

なお、base64関数は以下サイトを引用した。
https://qiita.com/leak4mk0/items/6c7f708dd59d52e0bc5c

ベースとしたサンプルプログラム:
https://github.com/wolfSSL/wolfssl-examples/tree/master/pq/tls/stm32

画像ファイルをBase64エンコード

手始めにクライアントからサーバに送信する画像ファイルをBase64変換し、
マイコンが読み取れるようにヘッダファイルに格納します。
今回は自作のBase64変換バッチファイル(base64_encoder.bat)を使って、
Base64変換します。
画像ファイルをドラッグ&ドロップすると、証明書形式でヘッダファイルが新規作成されます。

image.png

このヘッダファイルに以下の修正を手作業で実施(本当はここもバッチファイルに含めたい)
1.文字列「-----BEGIN CERTIFICATE-----」を「const char picture_encode_data_large[]="」に置き換える
2.全ての改行を削除
3.行末に";を追加する

これをlarge,middle,smallの三種類で実施することで、3つの画像ファイルに対するBase64変換ヘッダファイルが完成します。

image.png

どんな画像かは後のお楽しみ・・・

wolfSSLライブラリのビルド

wolfsslには大きく2つのgithubリポジトリがあります。
https://github.com/wolfssl/wolfssl:wolfssl本体
https://github.com/wolfSSL/wolfssl-examples:サンプルプログラムのためのソースコード

2つ目のソースコードは1つ目のソースコードを用いるため、
まずは1つ目のソースコードをビルドする必要があります。

gitクローンからビルドまでの流れ

git clone https://github.com/wolfSSL/wolfssl-examples.git
cd wolfssl
./autogen.sh
./configure --enable-kyber --enable-dilithium
make all
 ← 本来はここでビルドしたライブラリをテストするコマンドを打つ
sudo make install ← sudo入れないとpermmission denyされる

動作確認

サーバ側ターミナル画面

操作手順は、
1:まず先にサーバ側で、修正・機能追加したアプリケーションを実行
2:その後クライアント側で、デモコマンドを入力

その結果が以下である。

※TCP/IP通信を行っていないので、Wireshark上でTLS1.3による通信が確認できなかった

[UserName]@[UserName]-CF-Y7BWHNJR:~/wolfssl-examples/pq/tls/stm32$ sudo ./server-tls-uart-picture
Waiting for client
TLS Accept handshake done
Picture Data Size: 9775 [byte]  largeサイズの画像データを取得

[UserName]@[UserName]-CF-Y7BWHNJR:~/wolfssl-examples/pq/tls/stm32$ sudo ./server-tls-uart-picture
Waiting for client
TLS Accept handshake done
Picture Data Size: 6354 [byte]  middleサイズの画像データを取得

[UserName]@[UserName]-CF-Y7BWHNJR:~/wolfssl-examples/pq/tls/stm32$ sudo ./server-tls-uart-picture
Waiting for client
TLS Accept handshake done
Picture Data Size: 3733 [byte]  smallサイズの画像データを取得

クライアント側ターミナル画面

                                MENU

        l. Run TLS 1.3 Transport Large picture over UART
        m. Run TLS 1.3 Transport Middle picture over UART
        s. Run TLS 1.3 Transport Small picture over UART
Please select one of the above options: ← l+[Enter]
Large Picture Upload Server...
TLS Connect handshake done
Sending test string
Picture data sent complete!
TLS 1.3 Client: Return code 0

                                MENU

        l. Run TLS 1.3 Transport Large picture over UART
        m. Run TLS 1.3 Transport Middle picture over UART
        s. Run TLS 1.3 Transport Small picture over UART
Please select one of the above options: ← m+[Enter]
Middle Picture Upload Server...
TLS Connect handshake done
Sending test string
Picture data sent complete!
TLS 1.3 Client: Return code 0

                                MENU

        l. Run TLS 1.3 Transport Large picture over UART
        m. Run TLS 1.3 Transport Middle picture over UART
        s. Run TLS 1.3 Transport Small picture over UART
Please select one of the above options: ← s+[Enter]
Small Picture Upload Server...
TLS Connect handshake done
Sending test string
Picture data sent complete!
TLS 1.3 Client: Return code 0

受信データの確認

サーバ側ターミナル画面にて、ディレクトリstm32内のファイル一覧を出力します。
きちんとsmallサイズからlargeサイズまで画像ファイルが作成されていることが確認できます。
※recv_data_XXXX.jpgのXXXは、画像ファイルのサイズ[byte]を表す

[UserName]@[UserName]-CF-Y7BWHNJR:~/wolfssl-examples/pq/tls/stm32$ ls
recv_data_3733.jpg
recv_data_6354.jpg
recv_data_9775.jpg
---その他省略---

Linuxターミナル上ではjpgファイルを描画することはできないので、
scpコマンドを使ってWindows端末に送信する
※参照:https://qiita.com/WaatH5/items/ef976530976058aa2cb2

受信した画像データを確認
image.png

今後の課題

下記に5点の課題を書く

EthernetコネクタやWi-Fiモジュールを追加すべき

TCP/IP通信のテストとしてlocalhostを使うことは、WireSharkを使ったデバッグをすることができるので有益である。しかし、IoT端末のほとんどはゲートウェイを介した異なるネットワークへTCP/IP通信をする。
それを踏まえると、サンプルソフトウェアとして実践度合いが低いと感じてしまう

外部メモリに保存した秘密鍵が盗まれる

本ページ作品ではRAM上の鍵、証明書を使っているため該当しないが、
外部フラッシュや外部EEPROMに秘密鍵、証明書を格納してしまうと、
ハードウェアハッキングによってコピーデバイスを作成される恐れがある。
Winbond製フラッシュメモリではその外部フラッシュとマイコン間のI/F自体も暗号化する仕組みがあるようだ。

セキュア転送可能な画像ファイルサイズを拡大する

本ページ作品で取り扱った画像ファイルは予めサイズが小さくなるように加工をした。
組込みシステムでは使用RAMやバッファサイズ上限が予め決められているため、
下手に大きいサイズの画像ファイルをセキュア転送しようとすると、末尾が切れらてしまう。

TLS通信開始しようとすると、「sslレイヤーレコード長が不正」「通信バージョンが異なる」といったエラーが発生した

本ページに掲載している「サーバ側ターミナル画面」や「クライアント側ターミナル画面」の結果は、
全て連続してスムーズに転送完了したわけではない。
5回に1回ほど、上記のようなエラーが発生してしまう。
しかし、単純な10文字程度の文字列通信では1度も発生していないことから、
● データサイズが肥大化したことによる処理溢れ
● UART2通信のボーレート(115200)が遅い
と推測できる。

UART通信による暗号化通信なため、Wiresharkから観測不可

Wiresharkのusbmonを選択することでUARTの通信内容が確認できると考えたが、
どうしても権限エラーが解消できなかった。
たとえusbmon
のキャプチャが開始できても、
通信内容からプロトコルがTLS1.3であることを自動で認識してくれるとは思えない。
つまり、Wiresharkでパケットを確認するためには、
UART通信内容を一旦TCP/IPに変換する必要がある。

まとめ

STM32マイコンからサーバへ画像をセキュア転送することができた。
また、wolfSSLライブラリのwrite関数、read関数は平文でデータ受け渡しすることができると確認できた。

感想

●wolfSSLのSSL/TLS通信ライブラリは、それ自体が暗号化/復号処理してくれるので、
平文のままwrite関数を使って送信、read関数を使って平文を取得することができる。
つまり、送信したいchar型の文字列と送信先IPさえ決まっていれば簡単にスタートできる。

●筆者は今回2週間で本ページ作品を仕上げることができた。
元来、組込みシステムにおけるネットワーク通信(TCP/IP)に関する知識はある程度あるが、
暗号化処理の細かいアルゴリズムまでは知らなかった。
本作品の画像アップロードプログラムを用いて暗号化処理の詳しいソースコードを見てみる興味が湧いた。

●普段からWi-Fiモジュール単体またはATコマンドを使ったマイコンとWi-Fiモジュールとの通信を使って、
SmartHEMSや外出先からエアコンなどを操作する家電操作サーバを自作しているが、
無償版wolfSSLライブラリを使うことで、
今まで平文で送っていたHTMLファイルや室温情報を暗号化する術を身につけることができた。
STマイコン用のファームウェアパッケージも提供しているので、
ラズパイのみならず、STマイコンのAD変換によって得られた情報も
バンバン暗号化通信可能になる。

そして、暗号化通信でしか通信を受け付けていなかった
AWSなどの外部サービスサーバとの通信も可能になったので、
こちらもバンバン便利なIoT機器を自作していきたい。

参考

↓ 今回使用したサンプルプログラムの解説&動作確認をしている
https://www.youtube.com/watch?v=OK6MKXYiVBY&t=925s

↓ wolfSSLライブラリの使い方やTLS接続、暗号化に関する解説書
https://wolfssl.jp/wolfblog/2022/03/07/tlsv13book/

0
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
0
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?