Blanktar

  1. top
  2. blog
  3. 2020
  4. 10

Linux/Windowsのデュアルブート環境でBluetoothやBLEのデバイスを共有する方法

私のPCは普段使いのGentoo LinuxとゲームとかCADとか用のWindowsの両方をインストールしてあります。 そんなデュアルブート環境だと、OSを変えるたびにBluetoothデバイスを再ペアリングする必要があってちょっと面倒臭いことになります。

この原因は、ペアリングのときに生成されるキーをOS間で共有出来ないことにあるようです。 デバイスから見ると、「同じMACアドレスを名乗っているのに約束していたキーと違う。偽物だ!」みたいな感じらしいです。

調べてみたら結構簡単に合せられるっぽいので、設定してみました。 Bluetoothの場合とBluetooth LEの場合で一部手順が違うので、お使いのデバイスに合わせて対応してください。

1. Linux側でペアリングする

Windows側で生成したキーにLinux側を合せる手順を取るので、LinuxでペアリングしてからWindowsでペアリングする順序にします。 というわけで、まずはLinuxで普通にペアリング。

接続すると、/var/lib/bluetooth/{レシーバのmacアドレス}/{デバイスのmacアドレス}の中に接続情報が書かれたファイルが生成されるはずです。

2. Windows側でペアリングする

今度はWindowsを起動して、もう一度ペアリングします。

ここでWindowsとデバイス間で作られたキーの情報を使って接続するようにします。 別にLinux側で作ったやつをWindows側に持っていっても良いと思うのだけれど、Linux側の方がいじりやすいので。

3. Windowsのレジストリから情報を取り出す

Windowsが作ったキーが欲しいので、レジストリの以下の場所にある情報をエクスポートします。

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys

これを適当なエディタで開いて確認してみると、以下のような内容になっているはずです。 文字コードがUTF-16LEなので注意。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys]

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys\001bdcxxxxxx]
"MasterIRK"=hex:08,ce,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx
"cc988bxxxxxx"=hex:84,ed,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys\001bdcxxxxxx\d3bc56xxxxxx]
"LTK"=hex:a8,76,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,f8
"KeyLength"=dword:00000010
"ERand"=hex(b):eb,00,00,00,00,00,00,89
"EDIV"=dword:00ab0123
"MasterIRKStatus"=dword:00000001
"AuthReq"=dword:0000002d

4. Linuxに戻って接続情報を編集する

Linuxに戻って、/var/lib/bluetooth/{レシーバのmacアドレス}/{デバイスのmacアドレス}/infoを開きます。 レシーバとデバイスのmacアドレスは以下のコマンドで見付けられると思います。

# レシーバの一覧
$ bluetoothctl list
Controller 00:1B:DC:XX:XX:XX hostname [default]

# ペアリングしているデバイスの一覧
$ bluetoothctl devices
Device D3:BC:56:XX:XX:XX Microsoft Bluetooth Mouse
Device CC:98:8B:XX:XX:XX WH-1000XM3

ここからは、Bluetoothの場合とBluetooth LEの場合で分岐します。 開いたinfoファイルの中に[LinkKey]という記述がある場合はBluetoothの場合に、[LongTermKey]という記述がある場合はBluetooth LEの場合に進んでください。

Bluetoothの場合

必要な情報を探す

Windows側でエクスポートした.regファイルから、以下のようなセクションを見つけます。

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys\001bdcxxxxxx]
"MasterIRK"=hex:08,ce,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx
"cc988bxxxxxx"=hex:84,ed,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx

Keys\001bdcxxxxxxの部分がレシーバのmacアドレスになっているはずです。 この中からデバイスのmacアドレスと対応する値を見つけ出してコピーします。

今回は"cc988bxxxxxx"とペアリングしたいので、84,ed,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xxの部分をコピーします。 カンマは不要なので削除して、ついでにLinux側に合わせて大文字にしておきます。(小文字でも別に良いっぽいけれど)

ファイルに反映する

コピーしてカンマを消した値を使って、Linux側のinfoファイルを以下のような感じで編集します。

[LinkKey]
Key=84EDXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Type=4
PINLength=0

これでキーの移行は完了です。

Bluetooth LEの場合

必要な情報を探す

Windows側でエクスポートした.regファイルから、以下のようなセクションを見つけます。 Bluetoothの場合と違って結構長いです。

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Keys\001bdcxxxxxx\d3bc56xxxxxx]
"LTK"=hex:a8,76,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,f8
"KeyLength"=dword:00000010
"ERand"=hex(b):eb,00,00,00,00,00,00,89
"EDIV"=dword:00ab0123
"MasterIRKStatus"=dword:00000001
"AuthReq"=dword:0000002d

Keys\001bd0cxxxxxxの部分がレシーバのmacアドレスで、その後に続く\d3bc56xxxxxxの部分がデバイスのmacアドレスになっています。 複数デバイスある場合はこのセクションが複数あるはずなので、必要なものを見つけてください。

加工する

ここで必要なのは以下の3つの情報です。 ついでに色々加工をします。

  • LTK: hex:の後ろのa8,76,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,f8からカンマを取って、A876XXXXXXXXXXXXXXXXXXXXXXXXXXF8のようにして使います。
  • ERand: hex(b):の後ろのeb,00,00,00,00,00,00,89を左右反転(89,00,00,00,00,00,00,eb)してカンマを取って、10進数(9871890383196127467)にして使います。
  • EDIV: dword:の後ろの00ab0123を10進数にして、11206947のようにして使います。

諸々の変換はPythonとか使うと楽かもしれません。

>>> # LTKの加工
>>> 'a8,76,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,f8'.replace(',', '').upper()
A876XXXXXXXXXXXXXXXXXXXXXXXXXXF8

>>> # ERandの加工
>>> int(''.join(reversed('eb,00,00,00,00,00,00,89'.split(','))), 16)
9871890383196127467

>>> # EDIVの加工
>>> int('00ab0123', 16)
11206947

ファイルに反映する

加工した情報を使って、Linux側のinfoファイルのLongTermKeyセクションを以下のように書き換えます。

[LongTermKey]
Key=A876XXXXXXXXXXXXXXXXXXXXXXXXXXF8
Authenticated=0
EncSize=16
EDiv=11206947
Rand=9871890383196127467

値はそれぞれ、LTKKeyERandRandEDIVEDivになります。

5. Bluetoothデーモンを再起動して確認する

これで、Windows側で生成したキーをLinux側でも使えるようになっているはずです。 変更を反映させるために、デーモンを再起動させましょう。

$ sudo systemctl restart bluetooth

問題無く設定出来ていれば、再ペアリングすることなく両方のOSから接続出来るようになっているはずです。 やったね。


参考: