FreeRTOS＋LightWeightIP+mbedTLSのサンプル作成


この記事は、評価ボード「NUCLEOF429Zi」におけるFreeRTOS＋LightWeightIPでHTTP ServerやHTTP Clientを動作させるサンプルプロジェクトをベースに作成した、mbed-TLSを用いて暗号通信を行うプロジェクトについて説明します。

## 作成するサンプルの構成

今回作成するサンプルプロジェクトは下記のような構成のソフトウェアを作成します。

![サンプルのファームウェア構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/89906da6-4fd3-d556-39e9-b6db32010c40.png)


動作確認用のサンプルアプリケーションとして、HTTPのGETメゾッドを暗号化して送るものを作成します。
また、mbed-TLSを使用するうえで、乱数生成を行う必要があります。今回使用する評価ボード「NUCLEOF429Zi」には乱数生成を行ってくれるハードウェア(RNG)が搭載されているので、これを使用します。
また、その他に使用するEthernetドライバやLightWeightIPに関しては[こちら](https://qiita.com/tom_S/items/b152bfc8cf572c1a6f04 )の記事で使用したサンプルプロジェクト「LwIP_HTTP_Server_Netconn_RTOS」をそのまま流用します。

## プロジェクトの作成方法

[こちら](https://qiita.com/tom_S/items/b152bfc8cf572c1a6f04)の記事で作成したプロジェクト「LwIP_HTTP_Server_Netconn_RTOS」を流用し、SSL Clientとして動作するプロジェクトを作成します。
このプロジェクトにmbed-TLSとRNG用ドライバのラッパー、HTTPSの通信用のサンプルソースコードを追加することで簡易型HTTPS Clientとして動作するプロジェクトを作成します。

### mbed-TLSの設定

mbed-TLSのソースコードは、STM32CubeIDEとSTM32CubeMXをインストールしていれば下記の場所にあります。

```
<インストール先ディレクトリ>\STM32Cube\Repository\STM32Cube_FW_F4_V1.28.0\Middlewares\Third_Party\mbedTLS
```

このフォルダにある「include」「library」がmbed-TLSのソースコードとなるので、これをベースとしたプロジェクトに追加します。
LwIPや、FreeRTOSと同様、「LwIP_HTTP_Server_Netconn_RTOS\Middlewares\Third_Party」フォルダに「mbedTLS」フォルダを作り、そのフォルダの中に先ほど示した「include」「library」フォルダをコピー＆ペーストして配置します。

![mbedTLSフォルダ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d569065d-301d-0b3a-1e68-78c5b2252d03.png)


加えて、コンフィグファイルも追加します。デフォルトのコンフィグファイル「mbedtls_config.h」は下記にあるので、これを「LwIP_HTTP_Server_Netconn_RTOS\Inc」にコピー＆ペーストします。

```
<インストール先ディレクトリ>\STM32Cube\Repository\STM32Cube_FW_F4_V1.28.0\Projects\STM324xG_EVAL\Applications\mbedTLS\SSL_Client\Inc
```


### プロジェクト設定

また、プロジェクト設定に関しても修正します。下記の操作を行います。

- CubeIDEでプロジェクトを右クリック→Properties→C/C++ General→Paths and Symbolsをクリック。
  - 「include」タブを選択し、開いたダイアログのaddボタンを押し「../Middlewares/Third_Party/mbedTLS/include/」を追加

  ![パス指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/2f2049e7-8479-4be5-62df-70c47b695ae6.png)

- 「Symbols」タブを選択し、Addボタンを押して下記のように設定

![シンボル指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/6e0b58e6-7e44-1bf6-48a1-083b3f629939.png)

### mbed-TLSを動作させるために必要なドライバ設定

暗号化周りで使用するデバイスドライバをプロジェクトに追加します。
具体的なファイルとしては、「Drivers\STM32F4xx_HAL_Driver」にビルド対象として「stm32f4xx_hal_cryp.c」「stm32f4xx_hal_cryp_ex.c」「stm32f4xx_hal_hash.c」「stm32f4xx_hal_hash_ex.c」「stm32f4xx_hal_rng.c」を追加します。

![ドライバパス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/877a645e-219b-b2cb-6e27-57a6e9fa2686.png)


また、上記で追加したドライバを有効化させます。「LwIP_HTTP_Server_Netconn_RTOS\Inc」フォルダにある「stm32f4xx_hal_conf.h」を修正します。デフォルトでコメント化されている、「HAL_CRYP_MODULE_ENABLED」「HAL_RNG_MODULE_ENABLED」を定義された状態に修正します。

### Light Weight IP設定

ベースのプロジェクトから、Light Weight IPの設定をmbed-TLSように修正します。
「LwIP_HTTP_Server_Netconn_RTOS\Inc\lwipopts.h」において、下記のように定義を修正します。

```
#define LWIP_SOCKET                 1 /* ０になっているので修正 */
#define LWIP_DNS                        1
```

### mbed-TLS用のI/Oインターフェイス(net_sockets.c)

mbed-TLSとLwIP(Light Weight IP)をつなぐためのインターフェースとなる関数を作成する必要があります。公式サイトの[こちら](https://mbed-tls.readthedocs.io/en/latest/kb/how-to/mbedtls-tutorial/ )にもある通り、net_sockets.cというファイルを作成し、ここにサーバーとの接続に使用する関数である「mbedtls_net_connect」と送受信関数「mbedtls_net_recv」「mbedtls_net_send」等を定義します。
今回はSTM32CubeMXにて用意されている「net_sockets.c」を使用します。STM32CubeIDEとSTM32CubeMXをインストールしていれば、下記のファイルパスにあります。

```
<インストール先ディレクトリ>\STM32Cube\Repository\STM32Cube_FW_F4_V1.28.0\Projects\STM324xG_EVAL\Applications\mbedTLS\SSL_Client\Src
```

また、「STM32Cube_FW_F4_V1.28.0」フォルダはバージョンが変わるとフォルダ名が変更される可能性もあるのでご注意ください。

### RNGドライバの設定

RNGドライバとそれに付随するクロック設定を行います。
下記リンク先にあるリポジトリの「RNGWrapper.c/h」がこれに当たります。

https://github.com/TomSak13/NUCLEOF429Zi_mbedTLS_Sample 

これを「LwIP_HTTP_Server_Netconn_RTOS\Inc」と「LwIP_HTTP_Server_Netconn_RTOS\Src」に追加します。

### SSL Clientのサンプルソース

SSL Clientとして暗号化通信の設定をし、HTTPのGETメゾッドを送るサンプルソースです。下記リンク先にあるリポジトリの「SSLClient.c/h」がこれに当たります。

https://github.com/TomSak13/NUCLEOF429Zi_mbedTLS_Sample 

これを「LwIP_HTTP_Server_Netconn_RTOS\Inc」と「LwIP_HTTP_Server_Netconn_RTOS\Src」に追加します。
またSSLClient.cにて、接続先のSSLサーバーを起動するPCのIPアドレスを指定しています。よって環境に合わせて、下記のIPアドレスを示すマクロ「SERVER_NAME」を修正してください。

```
#define SERVER_NAME "192.168.11.11" // 接続先のSSLサーバーを起動するPCのIPアドレスに修正してください
```


### SSL Clientを起動させるサンプル

下記のようにmain()関数でRNGの設定を行い、SSL Clientをスレッドとして起動します。

```C
#include "SSLClient.h"
#include "RNGWrapper.h"


int main(void)
{
   HAL_Init(); 
  
   SystemClock_Config();
   /* RNG init */
   ConfigureClockForRNG();
   RNG_Init();
   /* SSLClient */
   osThreadDef(Client, SSLClient, osPriorityHigh, 0, configMINIMAL_STACK_SIZE * 20);
   osThreadCreate (osThread(Client), NULL);
   /* Start scheduler */
   osKernelStart();
   for( ;; );
}
```


### 動作確認方法

作成したSSL Clientのサンプルソースを動作させる方法を示します。
サンプルソースを動かすうえでのハードウェアの構成を下記に示します。

![接続図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/394d8714-16d5-0f0b-99bf-9e4e272d9352.png)

通信先となるHTTPS ServerはSTM32cubeMXにて用意されているPC用アプリケーションを使用します。ちなみに、このアプリケーションは[こちら](https://mbed-tls.readthedocs.io/en/latest/kb/compiling-and-building/compiling-mbedtls-in-mingw/ )でビルド方法が説明されています。

HTTPS Serverを先に動作させておく必要があるので、先に説明をします。そのあとにサンプルの動作方法を示します。

## 通信先のHTTPS Server

STM32CubeIDEとSTM32CubeMXをインストールしていれば、下記のファイルパスにある「ssl_server.exe」が今回使用する通信先のHTTPS Serverになります(「STM32Cube_FW_F4_V1.28.0」フォルダに関してはバージョンが変わるとフォルダ名が変更されている可能性もあるのでご注意ください)。

```
<インストール先ディレクトリ>\STM32Cube\Repository\STM32Cube_FW_F4_V1.28.0\Utilities\PC_Software\ssl_server
```

### 使い方

下記の手順を行えば、HTTPSのサーバーが起動します。

1. 「ssl_server.exe」があるフォルダでコマンドプロンプトを開く
2. 「SET MY_IP_ADDRESS=XXX」を入力し実行。XXXにssl_server.exeを起動するPCのIPアドレスを指定する
    - 例：「192.168.11.2」ならば、「SET MY_IP_ADDRESS=192.168.11.2」

3. 「ssl_server.exe」を入力し実行。コマンドプロンプトが下記のような画面となれば正常に起動しています

![コマンドプロンプト画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d587befc-d3b5-5e97-5149-b8e63ca3e650.png)



### SSL Clientを起動させるサンプル実行

下記のようにプロジェクトを選択状態にして、「Project」→「Buiild」でサンプルプロジェクトのファームウェアをビルドします。

![ビルドやり方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d9355133-5923-1212-4f17-c64fd5fb5323.png)


ビルドは、CubeIDEのConsoleに下記のようにメッセージが表示されていれば、成功です。これで「NUCLEO-F429ZI」に書き込むファームウェアが完成しました。

![ビルド成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/2c04cfca-a848-706e-7de6-15d2489685b4.png)


次に、このファームウェアをデバッグ実行します。「NUCLEO-F429ZI」の「CN1」のUSBの接続口(Ethernetの接続口と反対側の接続口)とPCをUSBケーブルで接続します。
デバッグ実行は、左上にあるプロジェクト「LwIP～」を右クリックし「Debug As」→「STM32 C/C++ Application」を選択します。

![デバッグ実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/42e33e46-430c-f822-9583-1b756176b6cc.png)


途中で下記のメッセージが表示されることがありますが、「Switch」を押してください。

![debug時メッセージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/4c54314f-3ec8-263e-e905-a76183cbd9cc.png)


下記のような画面になるので、赤枠内の再生ボタンみたいな形のボタンをクリックしてください。これでデバッグ実行することができます。

![デバッグ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/5640ce15-cd2d-45d7-0c0c-5ea8a77d9e04.png)


デバッグ実行し、HTTPのリクエスト送信が無事成功すると、HTTPS Serverを起動したコマンドプロンプトが下記のような画面となります。

![コマンドプロンプトの動確画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/ab5c0c33-d90f-d00c-0c88-55d1ebf981e5.png)