Windows Hello コンパニオンデバイスアプリについてのメモ

# Windows Companion Device について

どうも @82p です。
以前調べる機会があったので、個人用メモに近いですが公開します。
質問、ご指摘等いただければ感謝カンゲキ雨あられ、ってこれ元ネタなんなんですかね。

以下常体。

## コンパニオンデバイスアプリとは

まずはコンパニオンデバイスについて全く知らないという人は、[この動画](https://channel9.msdn.com/events/build/2016/p491)を先に見れば大体どんな事かは分かると思う。
どんなものかを私なりに言うと

* コンパニオンデバイスと Windows Hello の Companion Authentication Service と橋渡しをする UWP アプリ ※つまりはストアアプリ
* ロック解除を認証したデバイスで行える
* ただし Microsoft ストアに出すには Microsoft Certificate が必要(自分で作って試す分には Visual Studio があればOK)

公式Sample
https://github.com/Microsoft/companion-device-framework/tree/master/CDFSampleApp

## 出来ること

* デバイスのアプリからWindowsのロック解除をする。
* 例えばUSBデバイスを挿入するとロック解除が出来る
* ロック画面でキーを押すとスマホにプッシュ通知が飛びロック解除ができる…etc

YubiKeyを使ったコンパニオンデバイスアプリ
[YubiKey for Windows Hello](https://www.microsoft.com/ja-jp/store/p/yubikey-for-windows-hello/9nblggh511m5)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83984/679bb1d0-a955-0320-ceab-b26b03497f1a.png)

使ってみた記事 [IdM実験室: [Windows Hello]Yubikeyを使ってWindows 10 PCにサインインする](http://idmlab.eidentity.jp/2017/02/windows-helloyubikeywindows-10-pc.html)

## 出来ないこと

* **PCログインは出来ない**（あくまでロック解除のみ）
* Windows Hello のセットアップせずに利用は出来ない

>ただしセットアップさえしてあれば別のCredential ProviderでログインすればOK

## コンパニオンデバイスアプリに実装すべきこと

* デバイスの登録
* デバイスの削除
* デバイスの検出とロック解除イベントの監視
* ロック解除

## 認証プロセス

基本的には

* HMACを利用したChallenge and Response 通信をおこなう。
* 2つの共通鍵を使う
* 共有した鍵で Nonce の HMAC を計算し検証する。
* 通信用のキー（AuthKey）で、正しい通信であるかをチェック
* ロック解除用のキー(DeviceKey)で、正しいデバイスかをチェッック
* コンパニオンデバイスとアプリ間の通信は明確に規定されていない。（ただし十分にセキュアなプロトコルを使う）

### 登場人物

#### コンパニオンデバイス(以下デバイス）
PCのロック解除に使うデバイス。
USB,Bluetooth,インターネットなど経由でPCと通信する。
基本的には鍵の保管とサインを行う。

#### コンパニオンデバイスアプリ（以下アプリ）
コンパニオンデバイスと通信するアプリ。
UMPアプリでバックグラウンドで動く部分と、ロック解除時に動く部分がある。

#### Companion Authentication Service（以下サービス）
コンパニオンデバイスアプリのためのサービス。
Helloがセットアップされていれば動いてる（要確認）
デバイス情報の登録、TPMへのアクセスを担当する。

### 登録時

![2017-12-06_12h28_16.png](https://qiita-image-store.s3.amazonaws.com/0/83984/9c689dd3-7465-d17f-850b-b557bdd6a26a.png)

#### ①キーペアの作成のリクエスト
共通鍵となる2つのキーの生成をリクエストする。

#### ②キーペアの作成
2つのキーはデバイス側で生成しても良いし、アプリが作成してデバイスに送っても良い。※

#### ③共通鍵と共にデバイス情報をアプリに送る。
Device Key と Auth Key をコンパニオンデバイス側とWindowsのTPM下で共有すれば登録完了。

#### ④共通鍵とデバイス情報・そのほかメタデータを合わせてサービスに送る
サービス の API を叩いて、各種情報を登録する。2つの鍵は TPM に登録される。

じつは①～③はわりと自由に作っていい。

>※YubiKeyなど、デバイスに保存領域がなければアプリ側に鍵をwrapした形で保存するなどしても良い。


### 認証時

![2017-12-06_12h31_27.png](https://qiita-image-store.s3.amazonaws.com/0/83984/87c96cb7-95cf-2f17-7b5d-78f07670d63e.png)

#### ① イベント監視
アプリのバックグラウンドタスクが AuthenticationStageChanged などのイベントを監視して認証フローが開始される。※

#### ②認証開始
アプリからの CompanionDeviceID と ServiceAuthenticationNonce を サービス に送る。

#### ③SessionNonceの送信
サービス側では Nonce を保存された AuthKey で HMAC を計算し　Session Nonce, Device None と共にアプリに送る。
#### ④デバイスへ Nonce, HMAC の送信
③の Nonce と HMAC に加えて、HMACの計算元の ServiceAuthenticationNonce をデバイスに送る。

#### ⑤通信の検証とHMACの作成
Companion デバイス側でも AuthKey で HMAC を計算し、 送られてきたHMAC を検証する。正しい通信であれば デバイスキーで DeviceNonce のHMACキーを、AuthKeyで SessionNonce （とDeviceNonce?)のHMAC を計算し、アプリに投げる。

> もちろん、登録時と同じくこれらの処理をアプリ側で行い、コンパニオンデバイスは wrap された鍵の解除に使うだけでも良い。

#### ⑥サービスのAPI経由でHMACを送信
受け取った（あるいはアプリ側で計算した）情報をもとに サービスのAPIを叩く

#### 認証完了！

>※どのイベントを監視するかは認証時はシナリオによって異なるが、たとえばPCのロック画面をスライド（キータップ）する、だとか、
コンパニオンデバイスが挿入、あるいはモバイルアプリのボタンを押すなどの動作から発火させることが出来る。

## 参考

https://docs.microsoft.com/en-us/windows/uwp/security/companion-device-unlock
https://channel9.msdn.com/events/build/2016/p491
https://github.com/Microsoft/companion-device-framework/tree/master/CDFSampleApp