Linux Firefox で内蔵指紋リーダーを FIDO2 セキュリティキーとして使う

はじめに

今年度からうちの大学(千葉工業大学)のポータルサイトに二段階認証が導入されました。現状ではスマホの認証アプリ(Authenticator)でワンタイムパスワードを確認し、PC に手入力してログインしています。スマホでは指紋一発でログインできるのに、PC ではいちいちアプリを開いてコードを打ち込む必要があり、正直面倒です。

大学の案内 PDF では Chrome の拡張機能が推奨されていますが、自分の環境は Linux + Firefox。同じことを Linux の Firefox でもやりたいと思い調べてみました。

なぜ指紋リーダーが反応しないのか

Firefox で二段階認証の登録画面に進むと「touch your security key」と表示されますが、PC 内蔵の指紋リーダーはうんともすんとも言いません。

これは、PC の指紋リーダー(fprintd)とブラウザの WebAuthn/FIDO2 がまったく別のシステムだからです。

fprintdWebAuthn/FIDO2
用途OS ログイン、sudoWeb サイトの二段階認証
対応デバイスPC 内蔵指紋リーダーYubiKey 等の USB セキュリティキー
プロトコルPAMFIDO2/CTAP2

Windows Hello や macOS Touch ID は OS 側がこの2つを橋渡ししてくれますが、Linux にはその仕組みがありません。つまり、「セキュリティキーが存在しない」状態です。

解決策: tpm-fido2

調べたところ、tpm-fido2-thinkpad-linux というプロジェクトを見つけました。TPM 2.0 と fprintd を組み合わせて仮想の FIDO2 セキュリティキーを作り、ブラウザからは物理的な YubiKey と同じに見せるというアプローチです。

Firefox (WebAuthn API)

/dev/uhid (仮想 HID デバイス)

tpm-fido2 デーモン
    ├── TPM 2.0 (秘密鍵の保護)
    └── fprintd (指紋による本人確認)

ブラウザから認証リクエストが来ると、デスクトップ通知で指紋を求められ、タッチすると認証が完了します。

環境

項目内容
OSPop!_OS (COSMIC, Wayland)
ブラウザFirefox
指紋リーダーGoodix MOC Fingerprint Sensor
TPMTPM 2.0

セットアップ

前提条件の確認

まず TPM 2.0 があるか、指紋が登録済みか確認します。

# TPM バージョン確認(2 と出れば OK)
cat /sys/class/tpm/tpm0/tpm_version_major

# 指紋の登録状況を確認
fprintd-list $(whoami)

インストール

sudo apt install golang libfido2-dev libtss2-dev fprintd

git clone https://github.com/mc256/tpm-fido2-thinkpad-linux.git
cd tpm-fido2-thinkpad-linux
go build -o tpm-fido2
sudo cp tpm-fido2 /usr/local/bin/

uhid の権限設定

仮想 HID デバイスを作るために /dev/uhid の権限が必要です。

sudo chmod 666 /dev/uhid

起動

sudo tpm-fido2 --mode daemon

--mode daemon が重要です。デフォルトの native モードは Chrome 拡張機能用の Native Messaging で、Firefox では使えません。daemon モードは /dev/uhid 経由で仮想 HID デバイスを作成するため、Firefox でも Chrome でも動作します。

ハマったポイント: fprintd-verify のユーザー指定

起動自体は成功し、ブラウザで認証プロンプトも表示されるのに、指紋リーダーが全く反応しないという問題に遭遇しました。

原因はソースコードにありました。userpresence/userpresence.go の 103 行目:

// デフォルト: ユーザー名なしで fprintd-verify を呼ぶ
fprintCmd := exec.CommandContext(ctx, "fprintd-verify")

sudo で実行しているため、fprintd-verifyroot ユーザーの指紋を探しに行きます。しかし指紋は一般ユーザーで登録しているので、永遠にマッチしません。

修正

自分のユーザー名を引数に追加します。

fprintCmd := exec.CommandContext(ctx, "fprintd-verify", "ユーザー名")

修正後にリビルドします。

go build -o tpm-fido2
sudo cp tpm-fido2 /usr/local/bin/
sudo tpm-fido2 --mode daemon

これで指紋リーダーが正常に反応するようになりました。

動作確認

  1. sudo tpm-fido2 --mode daemon を起動
  2. Firefox で大学ポータルの二段階認証設定ページにアクセス
  3. 「touch your security key」が表示される
  4. デスクトップ通知「Touch fingerprint sensor to confirm」が出る
  5. 指紋リーダーにタッチ → 認証成功

これでスマホの認証アプリを開く必要がなくなり、PC だけで二段階認証が完結するようになりました。

まとめ

Linux では Windows Hello のような OS レベルの WebAuthn ブリッジがないため、PC 内蔵の指紋リーダーはブラウザの二段階認証にそのままでは使えません。tpm-fido2 を使えば TPM + fprintd で仮想セキュリティキーを作成でき、Firefox でも指紋認証が可能になります。

sudo 実行時に fprintd-verify のユーザー指定が必要な点だけ注意してください。

参考