nrf52でOTAする(Secure Bootloader+DFU)

# 前提
- nrf5Xの開発を行っている
- OTAをしたい(Bluetooth経由でアプリケーションをアップデートしたい)
- Segger Embedded Studioを使う
- OSXで開発

## 公式ガイド
- https://devzone.nordicsemi.com/nordic/short-range-guides/b/software-development-kit/posts/getting-started-with-nordics-secure-dfu-bootloader

ここみれば一応解決はします。

## 背景
- nrf52で開発しているとやはりFirmware OTA(Over-the-air)はしたい。
- そもそもOTAで見ず知らずのアプリケーションを書き込めるのは嫌だ
- SDK12以降はsecureじゃないDFUはできない[1]

## やること
1. secure bootloaderを書き込む
2. アプリケーションに署名をする


# 1.secure bootloaderを書き込む

## 事前準備もろもろ必要なもののインストール

### ひつようなもの
- homebrew
 - https://qiita.com/krtsato/items/ba567acacb93a7a02dd9
- python2
- pip
- nrf5 SDK
- nrfutil
- arm toolchain
- μECC(https://github.com/kmackay/micro-ecc)
- Segger Embedded Studio

## nrf5 SDK
https://www.nordicsemi.com/?sc_itemid=%7B21C26716-5F2C-4E2D-9514-C9B87B711114%7D
ココからダウンロードし、解凍。


## nrfutilのインストール
キーペアの作成、SDK用コードへの変換、署名に利用するツールです。
pythonの動作環境と、pipが必要です。
なお、nrfutilはpython2のみ対応。[3]
* version 6.00でpython3サポートがされたようです。(https://github.com/NordicSemiconductor/pc-nrfutil/releases/tag/v6.0.0)



```shell-session
$ pip install nrfutil
```

## arm toolchainダウンロード
- bootloaderのコンパイルというよりは、後述のmicroeccのコンパイルに利用します。

```shell
$ brew tap ArmMbed/homebrew-formulae
$ brew install arm-none-eabi-gcc
```


## μECCライブラリをインストール
- 署名の検証に必要。ARMtoolchainでコンパイルまで実行する。
 - おそらくライセンスの関係でバイナリが入っていない？ 
- ダウンロードし、解答したSDKフォルダの配下、`{SDK folder}/external/micro-ecc`に配置する。
- `{SDK folder}/components/toolchain/gcc/Makefile.posix`の`GNU_ROOT`を`/usr/local/bin`にかえる

```shell-session

$ cd {SDK folder}/external/micro-ecc/
$ git clone https://github.com/kmackay/micro-ecc.git
$ cd nrf52hf_armgcc/armgcc
$ make

```

## 秘密鍵・公開鍵のペアを作る
- 基本的にnrfのsecure DFUは電子署名の仕組みを利用しており、秘密鍵と公開鍵のペアが必要です。秘密鍵で署名しソフトウェアを作成し、Bootloaderには公開鍵を入れておき検証する。
- 参照先にも書いてありますが、あくまで署名なのでOTAする場合、パケットを取ればソフトウェアの中身は取れてしまいます。[2]

`nrfutil keys generate {filename}`でつくれる。
`nrfutil keys display --key pk --format code {input_privatekey} --out_file {outputfile_publickey(.c)}`
でnrfSDKで利用する形式(hex配列)に公開鍵を出力可能。


```shell
$ nrfutil keys generate private.key
$ nrfutil keys display --key pk --format code private.key --out_file dfu_public_key.c
```

## 作ったキーを配置する
- 作成したキー(ここではdfu_public_key.c)を下記フォルダに移す
- `{SDK folder}/examples/dfu/`

## secure bootloaderのサンプルプロジェクトを開く
- `{SDK folder}/examples/dfu/secure_bootloader/pca10040_ble/ses` にあるプロジェクトをファイルを開く。(segger embedded studioの場合)
- `sdk_config.h`の`NRF_DFU_HW_VERSION`を任意の数字に変える
- Jlinkなどでbootloaderを流し込む

あくまでサンプルプロジェクトなので、必要に応じて中身を変える必要はあるでしょう。

# 2. アプリケーションに署名をする
bootloaderはとりあえずできたので、次はアプリケーション側の対応を行います。

## コンパイルした後のバイナリを探し当てる
Seggerの場合だと、
`{project_root}/Output/Releases/Exe`にある、`.hex`ファイル。


## 署名する
```shell
$ nrfutil pkg generate --hw-version 1 --application-version 1 --application binary.hex --sd-req 0xA8 --key-file ../private.key  output.zip
```
`hw-version`: 先程指定した任意のHWVERSION.一致しないとロードできない。
`application-version`: 任意の数字。以前読み込んだバージョンと同等かそれ以上でないとロードできない。
`sd-req`: SoftDeviceのバージョン。後述。
`key-file`: 先程作った秘密鍵のファイルを指定

### sd-req
利用しているSoftDeviceのバージョンを記載する。
`nrfutil pkg generate --help`で候補一覧を見れる。

どれが入っているかわからない場合は、アプリケーションで取得することも可能。こんな感じ。

```c
  ble_version_t version;
  sd_ble_version_get(&version);
  NRF_LOG_INFO("SOFTDEVICE VERSION:%x",version.subversion_number);
```


## OTAする
- nrf toolboxもしくは nrfconnectアプリをスマートフォンにダウンロードする。
  - https://itunes.apple.com/jp/app/nrf-toolbox/id820906058?mt=8
  - https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrftoolbox&hl=ja
- できたZIPファイルを何らかの形でスマートフォンへ転送。
- sampleのbootloaderを利用している場合は、"DfuTarg"という名前で表示されるので、よしなにOTAを実行する。

## 残念なところ
じつはこのままだとDFUした後に再度DFUできないのですが、続きは気が向いたら。
このあたり使います。

-  https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.2.0/ble_sdk_app_buttonless_dfu.html

[1]:https://devzone.nordicsemi.com/f/nordic-q-a/19006/not-secured-dfu-sdk-12
[2]:https://devzone.nordicsemi.com/f/nordic-q-a/19769/secure-dfu-how-secure-is-it
[3]: https://github.com/NordicSemiconductor/pc-nrfutil