nRF52840-DKにOpenSKを入れてUSB FIDOキーにしてみた

やってみた系です。深く考えずにやっているので間違っているところもあるかもしれません。



# nRF52840-DKとは

[nRF52840](https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52840/GetStarted?lang=ja-JP)っていうSoCがありまして、チップ1個でUSB,BLE,NFCの機能を持っている優れものです。そのチップを乗っけて、電源、LED、ボタン、USBポートなどをくっつけた開発用キット（基盤）がnRF52840-DKです。これ１枚あればパソコンに接続して開発できるというオモチャです。

<img width="568" alt="nRF52840-DK.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/e43112bf-32c5-9a91-bc0b-cd3c6c68e9af.png">
**nRF52840-DK**


似たようなものに[nRF52840-dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle)というものがありまして、USB FIODキーというとこっちの方がしっくりくるのですがこちらは開発用キットみたいな便利なものではなくファーム書き換えが大変みたいなので今回は使いません。

<img width="276" alt="nrf52840-dongle.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/0f114384-041c-fc94-ebae-e459b131cc2f.png">
**nRF52840-dongle**


# OpenSKとは

FIDOキーの中のソフトウェアをGoogleが開発してオープンソースで公開したものです。[こちらのサイト](https://www.capa.co.jp/archives/33104)をみるとわかりやすいです。<br/>OSに[Tock](https://www.tockos.org/)、開発言語に[Rust](https://www.rust-lang.org/ja)を使っているという点で注目されています。

[OpenSKはGitHubで公開されていて](https://github.com/google/OpenSK)誰でも使うことができます。このソースをビルドしてnRF52840-DKとかnRF52840-dongleに書き込めば、FIDOキーになります。



# 環境

CTAPcsで動かさないのであればWindowsは不要です。基盤とホストPCを接続するのにマイクロUSBケーブルが必要です。

- nRF52840-DK (基盤)
- Mac OS X Catalina 10.15.4
- Windows 10 Pro 1909



# もくじ

- [1.nRF52840-DKを入手する](#1nrf52840-dkを入手する)
- [2.OpenSKをセットアップする](#2openskをセットアップする)
- [3.FIDOデモサイトで動かしてみる](#3fidoデモサイトで動かしてみる)
- [4.CTAPcsで動かしてみる](#4ctapcsで動かしてみる)



# 1.nRF52840-DKを入手する

## 買う

[NORDICのサイト](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)から買うことができます。購入先がいくつかあります。私はDigi-Keyから購入しました。
Digi-Keyでは¥5,654で送料は¥2,000だけど¥6,000以上買えば送料無料だということなので、nRF52840-dongle(¥1,154)も一緒に購入しました。１週間ほどでモノが届きました。(2020/6/14時点)

- **nRF52840-DK + nRF52840-dongle = ¥6,808（送料無料）**



## 動作確認

買ってきたばかりの基盤にはサンプルプログラムが入っています。基盤のLEDが光るだけのシンプルなものです。それでも正常に動くことを確認するには十分ですね。

[Getting started](https://infocenter.nordicsemi.com/topic/ug_nrf52840_dk/UG/nrf52840_DK/intro.html)をみて動かしてみます。ホストPCは入りません。

- `J2 Port`(micro usb)を電源に接続します。
- `SW9`を`VDD`にします。
- `SW8`を`ON`にします。
- 基盤に火が入り`LED1`がゆっくり点滅します。
- `Button`を押すと、対応する`LED`が光ります。

<img width="648" alt="nRF52840-DK_port.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/5a1da7b8-04f0-501e-e677-da5338dda083.png">



# 2.OpenSKをセットアップする

[Installation guide](https://github.com/google/OpenSK/blob/master/docs/install.md)を参考にします。

> The scripts provided in this project have been tested under Linux and OS X. We haven't tested them on Windows and other platforms.

ということなんで、Macでやります。



## 2-1.Macに必要なソフトをインストールする

先にいれとかないといけないものがあり。



### Rust

Macのターミナルから以下のコマンドでRustをインストールします。


```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```



途中インストールの方法を聞かれますが、`1)Proceed with installation (default)`で良いかと思います。

```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

info: downloading installer
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
...
  stable installed - rustc 1.44.0 (49cae5576 2020-06-01)

Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell run source $HOME/.cargo/env
```

`To configure your current shell run source $HOME/.cargo/env`ってことで、環境変数を更新する必要があるのでPCを再起動します。

念のためバージョンを確認しときます。

```
$ rustc --version
rustc 1.44.0 (49cae5576 2020-06-01)

$ rustup --version
rustup 1.21.1 (7832b2ebe 2019-12-20)

$ cargo --version
cargo 1.44.0 (05d080faa 2020-05-06)
```



### python3

python3はMac OS Xの場合、最初から入っているかと思います。

```
$ python3 --version
Python 3.7.3
```



### OpenSSL

- Homebrewを入れるとこからやらないといけないみたいです。

  - [Homebrewのサイト](https://brew.sh/index_ja)でインストールコマンドが書いてあるので、それをそのままターミナルで打ち込みます。これでbrewコマンドが使えるようになります。

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

  

- OpenSSLをインストール

```
$ brew install openssl
```

  


### J-Link Software

[SEGGERのサイト](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack)から`J-Link Software and Documentation pack for macOS`をダウンロードしてインストールします。

**J-Link Software and Documentation pack for macOS v6.80b([2020-06-05])**




## 2-2.OpenSKを書き込む


### GitHubからソースをClone

```
$ git clone https://github.com/google/OpenSK
```



### セットアップ

CloneしたOpenSKにあるsetup.shを実行します。


```
$ cd OpenSK
$ ./setup.sh
```

色々実行して、正常すると、`crypto_data`フォルダに秘密鍵とか証明書ができます。多分これを基盤に書き込むんでしょう。

```
crypto_data $ ls
opensk.key	opensk_ca.key	opensk_ca.srl	opensk_cert.pem
opensk_ca.csr	opensk_ca.pem	opensk_cert.csr
```



### Flashing a firmware

nRF52840-DKにOpenSKを書き込みます。

nRF52840-DKの`J2 port`とMacを接続して、nRF52840-DKの電源をONにします。

その状態でターミナルから以下のコマンドを実行します。

```
./deploy.py --board=nrf52840dk --opensk
```



しばらく時間がかかって基盤がピカピカして`You're all set!`となれば書き込み完了！

```
$ ./deploy.py --board=nrf52840dk --opensk

info: Updating rust toolchain to nightly-2020-02-03
info: syncing channel updates for 'nightly-2020-02-03-x86_64-apple-darwin'
info: checking for self-updates
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
info: Rust toolchain up-to-date
info: Building Tock OS for board nrf52840dk
    Finished release [optimized + debuginfo] target(s) in 0.04s
info: Building OpenSK application
   Compiling openssl-sys v0.9.58
   Compiling openssl v0.10.29
   Compiling ctap2 v0.1.0 (/Users/suzuki/openskwk/OpenSK)
    Finished release [optimized] target(s) in 19.50s
info: Generating Tock TAB file for application/example ctap2
info: Erasing all installed applications
All apps have been erased.
info: Flashing file third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin.
info: Flashing padding application
info: Installing Tock application ctap2
info: You're all set!
```



これでこのごつい基盤がFIDOセキュリティキーになりました。なったはずです。早速使ってみましょう。



**FIDOキーとして利用する場合は、基盤の`USB port`とPCをマイクロUSBケーブルで接続します。**<br/>**`J2 port`ではないので注意しましょう。**





# 3.FIDOデモサイトで動かしてみる

[YubiOnのFIDO2 体験デモサイト](https://yubionfido2demo.yubion.com/register_jp.html)でテストしてみました。

User Presenceの際はLEDがピカピカ光るので、Button1あたりを押しましょう。



| 環境                                               | Authenticator Type | Resident Key | 動作状況    |
| -------------------------------------------------- | ------------------ | ------------ | ----------- |
| Mac OS X Catalina 10.15.4 <br/>Chrome 83.0.4103.97 | Cross-Platform     | Off          | OK          |
|                                                    |                    | On           | OK          |
| Windows 10 Pro 1909<br/>Chrome 83.0.4103.97        | Cross-Platform     | Off          | **NG (*1)** |
|                                                    |                    | On           | OK          |
| Windows 10 Pro 1909<br/>Edge 44.18362.449.0        | Cross-Platform     | Off          | **NG (*1)** |
|                                                    |                    | On           | OK          |



#### *1

なんかダメなんですよねぇ。登録は成功するのですが、認証の途中で固まってしまいます。<br/>具体的には「セキュリティキーにタッチしてください」のメッセージでLEDがピカピカ光ってButtonを押すところまでは正常なんですが、Buttonを押してもブラウザ側が反応せず、先にすすみません。<br/>CTAPcsでは動くのでOpenSKの問題ではなく、Windows側のハンドリングの問題（ChromeとEdgeで同じ現象なので共通のAPIレイヤがあるんかな）ではないかと思います。



# 4.CTAPcsで動かしてみる

[CTAPcs](https://github.com/gebogebogebo/CTAPcs)っていうWindowsネイティブアプリ用のFIDOキーDLLがあるんですが、それでの動作確認してみました。examplesの`HIDTest01.exe`を動かします。

**ちゃんと動きます！（というか動くように修正しました）**

![HIDTest01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/466afbe7-36ef-7967-348a-bde0f8a338b9.png)


| 画面のボタン        | CTAPコマンド                          | 動作状況 | 備考                                                         |
| ------------------- | ------------------------------------- | ---- | ------------------------------------------------------------ |
| GetInfo             | authenticatorGetInfo                  | OK   |                                                              |
| MakeCredential      | authenticatorMakeCredential           | OK   | ResidentKey On/Off 両方OK                                    |
| GetAssertion        | authenticatorGetAssertion             | OK   | ResidentKey On/Off 両方OK                                    |
| setPIN              | authenticatorClientPIN<br/>setPIN     | OK   |                                                              |
| changePIN           | authenticatorClientPIN<br/>changePIN  | OK   |                                                              |
| ClientPINgetRetries | authenticatorClientPIN<br/>getRetries | OK   |                                                              |
| IsConnected         |                                       | OK   |                                                              |
| Wink                | CTAPHID_WINK                          | OK   |                                                              |
| List HID            |                                       | OK   |                                                              |
| Reset               | authenticatorReset                    | OK   | - 普通に実行してもリセットできない.<br/>- 基盤のButton1-4のどれかを押したままUSBに接続 --> コマンド送信 --> LED光る --> Buttonを押す -->リセット完了.<br/> |



# おつかれさまでした

意外と簡単です。

nRF52840-dongle使ってみたいんだよなぁ。