#はじめに
これはCTAPのお勉強をしたメモです。
WebAuthn(ウェブオースン)ではなく、CTAP(シータップ)であります。
今回はCTAP2の**NFC(Near Field Communication)**です。
###教科書
- CTAP仕様書 Client to Authenticator Protocol (CTAP) Implementation Draft, February 27, 2018
- WebAuthn仕様書 Web Authentication: An API for accessing Public Key Credentials Level 1 W3C Candidate Recommendation, 7 August 2018
###教材
###復習
#目次
1.Yubikeyについて
2.CTAP NFC
2.1 WindowsでNFCで通信するお作法
2.2 APDU Protocol
3.おまけ
#1.Yubikeyについて
Yubikey5です。
HIDだけでなくNFCでFIDO2(CTAP2)を話すことができます。
さらにFIDOだけでなく OTP,OpenPGP,PIV,OATH などいろんなことができるらしいです。
本デバイスを検証するにあたっていきなりハマったのですが、どうやらOTPの機能が有効になっているとFIDOの機能が使えないようで、CTAPのコマンドが通りません。
今回はCTAPの検証がしたいので、他の機能は無効にしました。
- (1) Yubikey ManagerをDLしてインストール
- (2) USBにYubikey5をさしてYubikey Managerを起動
- (3) InterfaceメニューからFIDO2関係だけチェックONに変更して「Save」
#2. CTAP NFC
NFCでYubikeyとお話する方法はCTAP仕様では
8.2. ISO7816, ISO14443 and Near Field Communication (NFC)
だけです。
つまり、基本的なことを知っていれば簡単です。
基本的なこととは何か?
- CTAP2コマンド
- NFC通信の基本
CTAP2コマンド
これはこれまでのお勉強メモで学習済みです。過去の投稿を見て思い出します。
NFC通信の基本
ISO7816, ISO14443と書いてあります。
これは以前検証したマイナンバーカードと通信する方法と同じで、winscard―API
を使ってAPDU
で通信する方法を意味します。
##2.1 WindowsでNFCで通信するお作法
エラー処理をちゃんとやるともう少し複雑になりますが、おおざっぱにはこんな感じです。
SCard系のAPIは決められた手順でCallするおまじないみたいなものです。
重要なのはScardTransmitで送信するAPDU
です。
APDUというバイナリのパケットにCTAPコマンドを詰めて送ります。この辺のめんどくささはCTAPHIDと同じです。ただCTAPHIDよりはずっと簡単です。
##2.2 APDU Protocol
CTAP仕様書 8.2.2. Protocol
The general protocol between a FIDO2 client and an authenticator over ISO7816/ISO14443 is as follows:
- Client sends an applet selection command
- Authenticator replies with success if the applet is present
- Client sends a command for an operation
- Authenticator replies with response data or error
クライアントとAuthenticatorのISO7816/ISO14443手順は以下の通り
- Clientはappletを選択するコマンドを送信する
- Authenticatorからの応答を受ける(appletへの接続)
- Clientは(CTAP)コマンドを送信する
- Authenticatorからの応答を受ける(CTAPコマンドの応答)
###appletを選択するコマンド
ISO7816/ISO14443というのはAuthenticatorがいわゆるICカードのふるまいをするということです。
ICカードは中にアプリ(applet)を複数格納できる仕様になっています。
Clientはまず、FIDOアプリに接続(SELECT)します。
CTAP仕様書 8.2.3. Applet selection
####例 SELECT FILE FIDO applet
// APDU
00 A4 04 00 08 A0 00 00 06 47 2f 00 01 00
// Response
55 32 46 5F 56 32 90 00
####APDU解説
APDU = [0x00, 0xA4, 0x04, 0x00], [0x08], [0xA0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01],[0x00]
固定値のところは仕様書に書いてある値をそのまま使えばいいです。
byte no | 項目名 | 値 | 説明 |
---|---|---|---|
0 | CLA | 00 | 命令クラス 固定値 |
1 | INS | A4 | コマンド名 Select File 固定値 |
2 | P1 | 04 | パラメータ1 固定値 |
3 | P2 | 00 | パラメータ2 固定値 |
4 | Lc | 08 | データサイズ 固定値 |
5-12 | Data | A0...01 | データ Selectするアプリ識別子(AID) 固定値 |
13 | Le | 00 | レスポンスバッファサイズ 00でOK |
####Response解説
Response = [0x55, 0x32, 0x46, 0x5F, 0x56, 0x32],0x90, 0x00
← 正常終了という意味
byte no | 項目名 | 値 | 説明 |
---|---|---|---|
0-5 | Data | 55...32 | version information ASCII変換で"U2F_V2" |
6 | SW1 | 90 | ステータスワード1 0x90で正常終了という意味 |
7 | SW2 | 00 | ステータスワード2 |
厳密にはversion informationの中身を見て自分とこの実装に対応しているかどうかチェックするみたいです。
ステータスワードはAPDUの仕様で以下のような意味です。
※Eternal Windowsより抜粋させていただきました。
###CTAPコマンドをAPDUで送信する
FIDO appletをSELECTしてResponseが正常にGETできたら、続けざまにAPDUでCTAPコマンドを送信します。
####APDU解説
APDU解説はもういいやってくらいのシンプルさなので Data In
のところだけ解説。
CTAPコマンドの長さ(バイト数)を1バイトで指定した後、CTAPコマンド(例によってCBORエンコードしたもの)を設定し、最後のLe
は0x00
を指定します。
####Response解説
そうするとレスポンスが返ってきます。
最初の1バイトがCTAPのステータスコード(6.3. Status codes)でその後ろがデータ。最後の2バイトがAPDUのSW1、SW2で0x9000
だったらOKということです。
####例 authenticatorGetInfo (0x04)コマンド
例えば CTAPのauthenticatorGetInfo コマンドの場合
//CTAP Command authenticatorGetInfo
04
// Response
00
A6 01 82 66 55 32 46 5F 56 32 68 46 49 44 4F 5F
32 5F 30 02 81 6B 68 6D 61 63 2D 73 65 63 72 65
74 03 50 FA 2B 99 DC 9E 39 42 57 8F 92 4A 30 D2
3C 41 18 04 A4 62 72 6B F5 62 75 70 F5 64 70 6C
61 74 F4 69 63 6C 69 65 6E 74 50 69 6E F5 05 19
04 B0 06 81 01
//CTAP Command authenticatorGetInfo
0x04
// Response
<Status>
0x00(CTAP1_ERR_SUCCESS Indicates successful response.)
<ResponseData-Decoded COBOR>
{
"1":["U2F_V2","FIDO_2_0"],
"2":["hmac-secret"],
"3":"-iuZ3J45QlePkkow0jxBGA",
"4":{"rk":true,"up":true,"plat":false,"clientPin":true},
"5":1200,
"6":[1]
}
これをAPDUにするとこうなります
// SendAPDU
80 10 00 00 01 04 00
// Response
00
A6 01 82 66 55 32 46 5F 56 32 68 46 49 44 4F 5F
32 5F 30 02 81 6B 68 6D 61 63 2D 73 65 63 72 65
74 03 50 FA 2B 99 DC 9E 39 42 57 8F 92 4A 30 D2
3C 41 18 04 A4 62 72 6B F5 62 75 70 F5 64 70 6C
61 74 F4 69 63 6C 69 65 6E 74 50 69 6E F5 05 19
04 B0 06 81 01
90 00
###CTAPコマンドをAPDUで送信する2
以下のケースに対応する仕様があります。
- 分割送信:送信するCommandが長い時の対応
- 分割受信:受信するResponseが長いときの対応
####分割送信
送信するAPDUのData In
では最初の1byte目でデータのレングスを指定します。
1byteということは0x00~0xFFの範囲です。
つまり、255byteを超える場合は1個のコマンドでは送信しきれません。
そんな時は分割して何回かに分けて送ります。
-
データにまだ続きがあるよってときは0x90から始まるこっちのAPDUで送ります。
※Data In
の書き方がわかりにくいですが、さっき説明したData Inの形式と同じで最初の1byte目がレングスです。つまりCTAP Command Byte || COBR Encoded Data
。
このコマンドに対する応答は9000
の2byteだけ返ってきます。
####分割受信
レスポンスにはレングスフィールドがないんですけど、同じように分割して送られて来る時があります。
そんな時はSW1が 0x61
になっています。ISO 7816-4の仕様のようです。
この辺のサンプルが
8.2.5. Fragmentation
のEXAMPLE 9に書いてあります。
#3.おまけ
WebAuthnぽいことができるWinデスクトップアプリ用ライブラリ WebAuthnModokiDesktopβのNFC対応を行いました。
ここで勉強した内容を反映しています。
もう、ソースがぐちゃぐちゃ...
#おつかれさまでした
NFCは意外と簡単でした。