私の技術系記事の多くは、まず自分で執筆し、その後 LLM を使って推敲していますが、この記事は大部分を LLM が書いています。LLM から解決方法を得て、実際に動作することを確認したうえで、その回答を記事としてまとめました。
この手順は、ファームウェア 3.0.3-0-g30917b92 を搭載した私の CanoKey Canary で検証しました。
1. 必要なツールを準備する
Debian または Ubuntu では、次を実行します。
$ sudo apt install python3-usb libusb-1.0-0
次のスクリプトでコマンドを送信します。
#!/usr/bin/env python3
import time
import usb.core
import usb.util
VID = 0x20A0
PID = 0x42D4
INTERFACE = 1
def apdu(device: usb.core.Device, command: str) -> bytes:
data = bytes.fromhex(command)
# Send command APDU.
device.ctrl_transfer(
0x41, # Host-to-device | Vendor | Interface
0x00, # CMD
0x0000,
INTERFACE,
data,
)
# Wait for execution to finish.
while True:
status = device.ctrl_transfer(
0xC1, # Device-to-host | Vendor | Interface
0x02, # STAT
0x0000,
INTERFACE,
1,
)
if bytes(status)[0] == 0x00:
break
time.sleep(0.05)
# Retrieve response APDU.
response = device.ctrl_transfer(
0xC1,
0x01, # RESP
0x0000,
INTERFACE,
1500,
)
return bytes(response)
def main() -> None:
device = usb.core.find(idVendor=VID, idProduct=PID)
if device is None:
raise SystemExit("CanoKey 20A0:42D4 not found")
print(f"Found {VID:04X}:{PID:04X}")
while True:
command = input("> ")
if command == "":
break
response = apdu(device, command)
print(f"< {response.hex(' ').upper()}")
if __name__ == "__main__":
main()
2. Admin アプレットを選択する
Admin アプレットのアプリケーション識別子(AID)は F000000000 です。次を送信します。
00 A4 04 00 05 F0 00 00 00 00
期待される応答:
90 00
この応答は、Admin アプレットが正常に選択されたことを示します。
3. Admin PIN の試行回数を使い切る
通常の認証を伴うリセットを実行できない場合、文書化された工場出荷時リセット手順ではこの操作が必要です。
まず、次のコマンドで試行回数を確認します。
00 20 00 00
初期状態では、デバイスは次の応答を返します。
63 C3
これは試行回数が3回残っていることを示します。
次の誤った PIN を意図的に指定する APDU を3回送信します。
00 20 00 00 06 30 30 30 30 30 30
PIN のバイト列は 000000 を表します。予想される応答は次のとおりです。
63 C2(残り2回)63 C1(残り1回)69 83(PIN がロックされた)
重要:現在の PIN を通常どおり使う必要がある場合は、試行回数を使い切らないでください。この手順では、PIN を意図的にロックすることで、ロック状態からの工場出荷時リセットを可能にします。
4. 工場出荷時リセットのコマンドを送信する
WebUSB スクリプトをもう一度実行し、リセット APDU を送信する前に Admin アプレットを選択します。
00 A4 04 00 05 F0 00 00 00 00
00 50 00 00 05 52 45 53 45 54
2つ目の APDU が工場出荷時リセットのコマンドです。
00 50 00 00 05 RESET
ここで RESET は、5バイトの ASCII 文字列 52 45 53 45 54 です。CanoKey では、この命令を INS=50 と定義しています。実行前に Admin PIN がロックされている必要があります。
5. LED の点滅に従う
コマンドを送信すると、CanoKey の LED が点滅を始めます。
- 点滅したら、すぐに本体に触れてください。
- 速い点滅と遅い点滅が順に現れるたびに、指示に従って本体に触れてください。
- 本体を接続したまま、Python スクリプトのポーリングを続けてください。
- スクリプトが最終応答を返すまで待ちます。
90 00
最後の 90 00 は、操作が正常に完了したことを示します。繰り返しのタッチ操作が完了すると、デバイスはこの応答を返します。
手順の要約
Admin アプレットを選択する
00 A4 04 00 05 F0 00 00 00 00
Admin PIN をロックする
00 20 00 00 06 30 30 30 30 30 30 を3回送信します。
工場出荷時リセットを開始する
00 50 00 00 05 52 45 53 45 54
リセットが完了するまで本体に触れる
点滅のたびに指示に従って本体に触れ、応答が 90 00 になるまで続けます。