Bluetooth 5.1 Headset In Dual Boot Environment
===============================================

## Intro
In this tutorial we will attempt to allow the same bluetooth device (a Bose Quietcomfort Ultra headset to be precise) to be paired and connected to a dual-booted Windows/Linux system without needing to re-pair the headset every time you switch between operating systems. The process is cumbersome and requires many steps but it is not impossible.

## The Problem
When pairing bluetooth devices to each other, those devices keep track of each other via a mac address: an unique number-character combination that identifier a particular device. Pretty much every device that is used to connect to something whether it's a set of headphones, network adapter, an usb stick or a game controller, has an unique mac address attached to it.

Imagine then that you pair a set of headphones to your computer. The computer now has a record of your headphones mac address and the headphones has a record of your computer's bluetooth adapter's mac address.

Mac addresses however, are only half the equation. The other half is how these devices authenticate with each other so your headphones know which computer is allowed to send it sound and which is not. This is done via keys that computer keeps in it's record and these keys are generated every time a pairing occurs.

So let's say that you pair your headphones to a Linux computer and then boot into a Windows operating system on the same computer and attempt the pairing again. It will work, but now
the only operating system that has the correct key, provided by the headphones, is on Windows. Reboot to Linux and attempt to connect and you are met with an error since your Linux machine,
despite having a record of the headphone mac address, now has the wrong key to authenticate and the headset has already cleared it's internal records for any authentication keys belonging to Linux. The simple rule of thumb is: one mac address, one set of keys.

## The solution briefly
The solution to this conundrum is simple (how to make that solution happen, not so much): copy the keys from Windows into Linux. Now there are multiple projects out there that have attempted to fix this problem but they seem to work only for older devices. More specifically devices that operate with bluetooth 4 and and maybe 5. So we'll do this by hand for now.

## About Bluetooth 5.1
Bluetooth had some changes to it as far as key management after version 5 or 5.1 (don't remember which). What happened was that things got more complicated (shocker that). In earlier versions of bluetooth, there was just one key to be concerned about. Now there are several. So if you do not find in your .reg file the necessary keys, there is a change that your device is of the older version. That means, you actually might get off this exercise slightly easier than I did. I suggest looking to [Arch Wiki](https://wiki.archlinux.org/title/bluetooth#Dual_boot_pairing) or search for dual boot bluetooth device and you'll come across several tutorials that will go through it. The process is virtually the same, just much simpler.

I'll still suggest reading through the relevant wiki section for reference and potential extra help if these instructions prove insufficient.

## How to make it happen

Let's break this down into steps. We need to...

1. Pair and connect our device in Linux
2. Pair and connect our device in Windows
3. Extract the necessary registry keys from Windows
4. Transfer (and transform) the keys to Linux
5. Update Linux configuration so headset will accept new keys

Easy right? Weelll... the first couple of steps are.

### Phase 1: Pairing On Linux
The first step is rather simple. We pair and connect our bluetooth headset with Linux.

### Phase 2: Bootin Into Windows And Pairing Again
Step 2, not so difficult either. Just make sure the headphones are in pairing mode and once Windows pairs and connects, we are in business.

### Phase 3: Extracting Keys
Here's where things get a little trickier. We need access to windows registry to extract our keys and we can't just launch regedit. This is due to the fact that we need extraelevated privileges, aka SYSTEM account, to view all the information we need. To do that, we use [pstools](https://learn.microsoft.com/en-us/sysinternals/downloads/pstools). What you do is this:

1. download pstools and extract to a folder (I use *C:\Programs\pstools*)
2. open command prompt, powershell or windows terminal **as** administrator
3. navigate to folder pstools
4. run `.\PsExec.exe -i -s regedit`

We should see now windows registry editor open.

^^^
![Windows registry when opened with PsExec](assets/windows-registry.png)
^^^ Windows registry when opened with PsExec

Navigate down the registry heys
- HKEY_LOCAL_MACHINE
-> SYSTEM
-> CurrentControlSet
-> Services
-> BTHPORT
-> Parameters
-> Keys
-> [BLUETOOTH ADAPTER MAC ADDRESS]

Beneath [BLUETOOTH ADAPTER MAC ADDRESS] there is mac addresses for each bluetooth device paired. Other guides as I recall will ask to export a specific device registry keys but what we will do is export the the entire [BLUETOOTH ADAPTER MAC ADDRESS] device. That should give us a *.reg* file that looks something like this:

```
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Keys\1cc10c325f27]
"CentralIRK"=hex:25,02,6b,0e,c2,1a,f8,37,8c,c3,d0,d2,7a,f9,4a,6e
"acbf71cef184"=hex:d8,97,cd,2f,7b,6c,ab,e2,12,62,c1,db,46,e5,b4,fe

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Keys\1cc10c325f27\acbf71cef184]
"LTK"=hex:ef,c1,03,0c,cb,d1,90,f1,61,14,b2,1a,52,45,11,ba
"KeyLength"=dword:00000010
"ERand"=hex(b):00,00,00,00,00,00,00,00
"EDIV"=dword:00000000
"IRK"=hex:1b,5a,69,12,cc,06,0b,23,91,ab,6f,e8,8c,fe,ba,7e
"Address"=hex(b):84,f1,ce,71,bf,ac,00,00
"AddressType"=dword:00000000
"CEntralIRKStatus"=dword:00000001
"AuthReq"=dword:00000020
```

We are interested in three lines:
1. "acbf71cef184"=hex:
2. "LTK"=hex: key
3. "IRK"=hex: key

We copy these three lines or the entire file to an usb stick or something else that can be accessed via Linux.

We are done with Windwows so let's reboot back into Linux.

### Phase 4: Transforming keys
The keys from Windows are not applicable as themselves. We need to do some modifying to them. Don't worry. It's not too difficult. What we must do is:

1. Remove commas
2. Turn the entire string to uppercase

```
"acbf71cef184"=hex:d8,97,cd,2f,7b,6c,ab,e2,12,62,c1,db,46,e5,b4,fe
becomes =>         D897CD2F7B6CABE21262C1DB46E5B4FE

"LTK"=hex:ef,c1,03,0c,cb,d1,90,f1,61,14,b2,1a,52,45,11,ba
becomes =>         EFC1030CCBD190F16114B21A524511BA

"IRK"=hex:1b,5a,69,12,cc,06,0b,23,91,ab,6f,e8,8c,fe,ba,7e
becomes =>         1B5A6912CC060B2391AB6FE88CFEBA7E
```

### Phase 5: Updating Linux configuration

It is recommended to stop bluetooth service at this point.

```
systemctl stop bluetooth
```

Then we navigate to the *[BLUETOOTH ADAPTER MAC ADDRESS]* folder in our Linux bluetooth configuration.

```
cd /var/lib/bluetooth/[BLUETOOTH ADAPTER MAC ADDRESS]
```

Inside we will find folders for each bluetooth device similarly like in Windows registry. We make a copy of it as a backup 

```
cp -r [DEVICE MAC ADDRESS] [DEVICE MAC ADDRESS].orig
```

And then modify the `info` file inside *[DEVICE MAC ADDRESS]* folder. It should look something like this.

```
[General]
Name=Bose QC Ultra Headphones
Class=0x2c0404
AddressType=static
SupportedTechnologies=BR/EDR;LE;
Trusted=true
Blocked=false
Services=...

[DeviceID]
Source=1
Vendor=158
Product=16486
Version=340

[LinkKey]
Key=[KEY FROM PHASE 1]
Type=7
PINLength=0

[IdentityResolvingKey]
Key=[KEY FROM PHASE 1]

[PeripheralLongTermKey]
Key=[KEY FROM PHASE 1]
Authenticated=2
EncSize=16
EDiv=0
Rand=0

[SlaveLongTermKey]
Key=[KEY FROM PHASE 1]
Authenticated=2
EncSize=16
EDiv=0
Rand=0
```

Now we need to replace some keys with the one's modified a moment ago and here's how to use them:
- The device key (D897CD2F7B6CABE21262C1DB46E5B4FE) goes to *[LinkKey]* section
- IRK (1B5A6912CC060B2391AB6FE88CFEBA7E) goes to *[IdentityResolvingKey]* section
- LTK (EFC1030CCBD190F16114B21A524511BA) goes to *[PeripheralLongTermKey]* and *[SlaveLongTermKey]* sections

Like so:

```
[General]
Name=Bose QC Ultra Headphones
Class=0x2c0404
AddressType=static
SupportedTechnologies=BR/EDR;LE;
Trusted=true
Blocked=false
Services=...

[DeviceID]
Source=1
Vendor=158
Product=16486
Version=340

[LinkKey]
Key=D897CD2F7B6CABE21262C1DB46E5A4AF
Type=7
PINLength=0

[IdentityResolvingKey]
Key=1B5A6912CC060B2391AB6FE88CDADC7E

[PeripheralLongTermKey]
Key=EFC1030CCBD190F16114B21A527424BA
Authenticated=2
EncSize=16
EDiv=0
Rand=0

[SlaveLongTermKey]
Key=EFC1030CCBD190F16114B21A527424BA
Authenticated=2
EncSize=16
EDiv=0
Rand=0
```

We save the file and restart bluetooth service.

```
systemctl start bluetooth
```

Now the headphones should work both on Windows and Linux with no worries.