nRF Connect SDK:DFU(Ver. 2.3+)

# 集大成
過去に書いた記事は(その当時の苦労を汲み取る意味でも)ずっと残しておく方針です。バージョンアップで全く通用しなくなったり、あるいはその時点での理解が間違っていて変なことを書いているといった場合もしばしばあるのですが、それも含めての記録です。

::: note
昔はどんなのだったか、ってのも分かるしね・・・別に要らんけど(笑)
:::

https://qiita.com/yoshihiro0709/items/cbe4a8d5463bcd622405

https://qiita.com/yoshihiro0709/items/985ed9040015572833fb

# バージョンアップで簡単になった
つい先日、nRF Connect SDKがVer. 2.3にアップデートされました。リリースノートはこちら

https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases/release-notes-2.3.0.html

ザーッと眺めていくとWorking with nRF52 Seriesの欄にFOTA用にKConfigを追加したという記載があるのを見かけました。お、これは早速試してみるしか！ということで試してみました。使用するサンプルプロジェクトは何でもよいのですが、あらかじめBluetooth部分が実装されているperipheral_XXXXというサンプルを使うと何も考えずに試すことができます。

::: note
今回はPeripheral_BMSとPeripheral_UARTを使っています。
:::

## 実際の設定
まず、最初にMCUBootloaderを有効にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/56042347-c013-4cff-9d15-f3c4a0e98274.png)
次に実装されたというDFU関連の設定を有効にします。OTA DFU over bluetoothをチェックすると全部強制チェックが入りますが依存関係的に正しいので大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/3a32db83-dca6-6894-4be9-8084b05e7847.png)
そしてコンパイルしてダウンロードしてみると・・・。
![Screenshot_20230308-180457.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/c053dbe0-6918-0d7d-6a45-d16e8e6c15ed.png)
あらま、なんともあっさりできてしまいました。こりゃ簡単ですね！最初のころに色んな設定を追加したり、ソースコードにDFU用の記述を追加したり、分からなくて英語のやりとりをひたすら読んだりとやっていたのがアホらしくなるくらい簡単です。いや、簡単であることに越したことはないのです。別に技術者だって好きで難しいことがやりたいわけではないのです。

::: note
たぶん・・・一部の変な人はそうじゃないかもね(笑)
:::

# 再びSecure DFUに挑む
はて、何回挑戦しているのだろうか・・・(笑)
今回のバージョンアップでDFUが簡単に実装できるようになったのを機に、今度こそはSecure DFUを実装してみせると誓って再びドキュメントやNordic DevZoneを漁りまくりました・・・とその前に、これってやっぱりSecureじゃないよね、ということを念のため確かめることに。

::: note warn
過去にも説明していますが厳密にはNon Secureというモードは存在せず、秘密鍵を指定していないのでSDKに含まれているサンプルのECDSA-256を使うために秘密鍵がバレているという状態です。
:::

## やはりSecureではなかった(当たり前)
違うプロジェクト(Peripheral_UART)を作って・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/a1481284-4a71-5fcc-37e4-70bfedceed91.png)
先ほどと同じ設定をしてコンパイルします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/56042347-c013-4cff-9d15-f3c4a0e98274.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/3a32db83-dca6-6894-4be9-8084b05e7847.png)
nRF SDK時代はDFUパッケージを別スクリプトで作成するようになっていたのでDFU後のファームウェアがDFUの機能を持っていないということもできた(二度とDFUできなくなるので普通はそんなことしません)のですが、NCSではDFUを実装する設定をしないとコンパイラがapp_update.binやdfu_application.zipを生成してくれないのでDFUできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/56b99857-9ff8-2adf-5b14-dffd039ecc9d.png)
app_update.binとdfu_application.zipはどちらを使ってもいいのですが、nRF SDKからの流れでなんとなくzipファイルを使うのがいいかなと思っています。

::: note
完全に雰囲気です(笑)
dfu_application.zipはapp_update.binとmanifest.jsonを無圧縮zipしたものなのでほぼ同じです。
:::

![Screenshot_20230309-103448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/3a5cd008-67b1-4e8e-0ece-072c7ba2395a.png)|![Screenshot_20230309-103502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/612e0944-0505-cd92-5cc9-99179a844591.png)
ちゃんと(？)DFUできました。接続名はBMSのままですがサービス名が変わっています。
![Screenshot_20230309-103542.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/b5b7f1eb-be68-6fb5-061c-69d7d94de6a0.png)
ということで、やっぱりセキュアではありませんでした。そりゃ当たり前ですよね、だって何も設定していないんですもの・・・。

::: note
ここまで定期(笑)
:::

## 不具合(？)が直っていることを期待して
前回のSecure DFUでは関連する設定と思われるCONFIG_MCUBOOT_SIGNATURE_KEY_FILEあたりが実は不具合でうまく動いていないのではないかと思っていました。なぜCONFIG_MCUBOOT_SIGNATURE_KEY_FILEじゃなくてCONFIG_BOOT_SIGNATURE_KEY_FILEを指定しろと出てくるのか意味が分からないからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/ed81c950-f434-1f1f-5338-0f859afed29b.png)

::: note
画像は前回の使い回しです・・・
:::

これが不具合だったとすればVer. 2.3ではもしかして直っているかも知らない！と少しだけ期待して動かしてみましたが・・・やはりダメでした。同じことを言われてしまいます。
## とうとう見つけた！
となるとやっぱり根本的に何かが間違っているのだろうなと思ってひたすらこの関連で検索しまくりました。そしてついに！見つけました。

https://devzone.nordicsemi.com/f/nordic-q-a/88416/mcuboot-sign-the-firmware

内容そのものはVer. 1.9.1のものなので若干古いのですが、Answerの部分にどうやって設定するかが記載されているのを見つけました。

```
CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
```

::: note warn
このあたりのコマンドは2.0以降は削除されています
:::

設定するキーはCONFIG_BOOT_SIGNATURE_KEY_FILEで正しいようです。ただし設定の仕方が特殊な記述になるようで、child_imageフォルダを作ってその下にmcuboot.confという名前でファイルを作らなければいけないとのこと。また、上記コマンドは削除されているため、現在はECDSA-256固定となっており、またそのキーファイルのパスは絶対パス指定である必要があるみたいです。

::: note warn
そんなの分かんねーよ・・・orz
:::

ということで早速作ってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/4d569ee4-0843-6add-5907-115e054d24fa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/2399a346-47b6-b8ab-1727-5537177199b1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/6c37d0fc-f674-3dd1-90e4-1d490c8958ba.png)
そしてコンパイルしてみると・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/40d39f5e-b293-b4ca-8ddd-98c360ac6600.png)
おお！おおお？！
キーファイルを認識している！
ということは・・・。
これは・・・イったのか？
### 補足
キーファイルは最初の記事でも記載しましたが付属のスクリプトを使ってPythonで生成することができます。余談ですがECDSA-256なのでnRF SDK時代に作成した秘密鍵(nRF SDKでは一般的にprivate.keyという名前のファイル)でも使えます。

```
python keygen.py --private -o priv.pem
```

## Secureになったのか確認
早速コンパイルしたイメージを書き込み、先ほど使ったPeripheral_UARTのdfu_application.zipでDFUを再び試みてみます。SecureになっていればNon SecureであるPeripheral_UARTのイメージには書き換わらないはずです。
![Screenshot_20230309-112412.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/16ec58d7-0430-299a-2388-878c54b15fbc.png)|![Screenshot_20230309-112425.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/7f74c60c-665e-de2c-b3a9-6e44aa5d9488.png)
![Screenshot_20230309-112545.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/75d343e7-bb3a-0258-aecc-20019aa34d80.png)
！！！
書き換わっていない！
省略しますが、同じキーファイルを使ってコンパイルしたイメージでは当然DFUで書き換えることができます。
# 総括
長い闘いがやっと終わりました・・・。