Understanding why a DHK check is failing with Arduino BLE

Hi,

Not sure if there is a category for this that is more suitable, but this one seems generic enough.

So i am currently trying to implement the ability to initiate pairing using the Arduino BLE library on an Nrf52840 chip (seeed Studio Seeed XIAO BLE nRF52840 to be precise).

My goal is to be able to connect to an Xbox 1 S Controller that supports BLE as its protocol and read the inputs from the controller.

I have trawled the internet extensively for answers to the this and arrived at the conclusion that it needs pairing to encrypt the connection to be able to read the report map, which is not allowed with a 'simple connection' established only. This ability is not currently implemented in the Arudino BLE library either as far as i understand. There was an implementation added to accept a pairing request, but not initiate one, so i am trying to implement this myself.

I have managed to get quite far through the pairing process and i am at the point where i am sending a DHK check to the controller to verify the connection as the last step before i encrypt the connection using the LE_Encrypt command. I am trying to implement JustWorks Pairing only, as my device has no display or buttons and the controller reports its IO cap and NoInputNoOutput.

I have captured a trace of the connection process between my laptop and the controller using Wireshark beforehand to guide me along the way in terms of the flow, while cross referencing the BLE 5.0 spec.

As per this diagram from the spec:

the Ea check is failing.

I have verified the f5 and f6 functions are working correctly using sample inputs and output from the spec and writing test functions. These can be found on my fork of the arduino BLE library along with the changes i have made so far. I have tried to keep my new logic segregated so it can be run as a standalone process without upsetting the existing 'accept pairing' code:

I have checked over the requirements of these functions and i am at a dead-end as i am fairly confident i am passing the correct inputs to these functions as per:

and

Is there anyone out there with any extensive knowledge/bright ideas on what i could do to try and narrow down the cause of the issue i am seeing?

After verifying the implementations of f5 and f6 and triple checking the inputs i am passing in my code, apart from a possible endian mismatch somewhere or incorrectly calculated DHK, i am at a loss. I am calculating the DHK key using the LE_Command. i havent tried to roll my own.

I consistently get back

0x05 - 0x0B which i understand is

Pairing Authentication failed - DHK value mismatch

Here is my Serial Log debug output from my implementation thus far:

SCANNING...
CONNECTED TO Xbox Wireless Controller
*** STARTING STAGE 1 ***
Device with handle: 0is connected and MTU has been exchanged. Beginning pairing operation in ATT layer...
Set Peer as NOT the initiator of the pairing operations as we have inititated it
Sending Pairing Request to HCI Layer0
Sending Pairing Request to L2CAPSignaling Layer0
Creating Pairing Request payload struct in L2CAP layer...0
Local IO Cap set as: 0x9, 0x0, 0x3
Creating Pairing Request payload struct in L2CAP layer...0
Sending Pairing Request ACL Packet...0
ACL Packet Data:0x1, 0x3, 0x0, 0x9, 0x10, 0x2, 0x3
Pairing Request ACL Packet Sent!0
Peer encryption : 0b1
Pairing Request sent. Polling for new responses...0
handleSecurityData: code: 0x2
rx security:0x2, 0x3, 0x0, 0x9, 0x10, 0x2, 0x3

*** STARTING STAGE 2 ***
Response to Send Pairing Request Received in L2CAPSignaling Layer from: 0
ioCapability: 3
oobDataFlag: 0
authReq: 9
maxEncSize: 10
initiatorKeyDistribution: 2
responderKeyDistribution: 3
Pairing Request Response from peer device has payload: 0x2, 0x3, 0x0, 0x9
Response has properties: bonding, no CT2, no KeyPress, no MITM, SC, Set Peer IO Cap as: 0x9, 0x0, 0x3
Peer encryption : 0b1
Requesting Public Key Generation from Controller
Public Key Generation requested!
Set Peer encryption : PAIRING REQUESTED_ENCRYPTION
Key read success
Setting local public key buffer as: 
0x3A, 0xA9, 0xBC, 0x8, 0xFC, 0x3C, 0x35, 0x11, 0xF9, 0xD3, 0x90, 0x73, 0x2F, 0x41, 0x2D, 0xB5, 0x65, 0xE8, 0x66, 0xA2, 0xED, 0x3B, 0xE5, 0x5F, 0x20, 0xA3, 0x47, 0x86, 0x6C, 0xCD, 0x8B, 0x6, 0xC1, 0x7, 0x39, 0xB0, 0xE2, 0x41, 0xBE, 0xBA, 0x16, 0x9F, 0xF4, 0x3A, 0xD9, 0x9E, 0x40, 0xA7, 0x11, 0xA5, 0xC7, 0x55, 0x39, 0xD5, 0x7D, 0xD4, 0xF, 0x8F, 0xD3, 0xB3, 0x9B, 0x4F, 0x68, 0xE0
Set Peer Encryption to SENT_PUBKEY
handleSecurityData: code: 0xC
rx security:0xC, 0x78, 0x9B, 0x4D, 0xCA, 0xF4, 0x6B, 0x3E, 0x30, 0x41, 0x19, 0x18, 0x7, 0xE, 0xC2, 0x2F, 0x5, 0x29, 0x34, 0x5F, 0xA2, 0x4E, 0xB2, 0xF4, 0x36, 0xF2, 0xB0, 0xB0, 0x76, 0xA6, 0x7F, 0x8B, 0x9F, 0x55, 0xDF, 0x30, 0x6A, 0xFF, 0xA1, 0xBB, 0xDB, 0x17, 0x71, 0x22, 0x41, 0xF2, 0xD1, 0xE1, 0xE7, 0x6B, 0x25, 0xC9, 0x8A, 0x94, 0xA8, 0x6C, 0x65, 0xA0, 0xCD, 0x9A, 0x38, 0xE6, 0xBB, 0x2D, 0x81
Set Peer Encryption to REQUESTED_ENCRYPTION
[Info] Pairing public key
Requested encryption stored.

*** STARTING STAGE 3 ***
handleSecurityData: code: 0x3
rx security:0x3, 0xB0, 0xAB, 0xA2, 0x20, 0x5D, 0x37, 0x62, 0xEF, 0x5D, 0xA4, 0xD7, 0x8A, 0x8B, 0xAF, 0x77, 0xB9

*** STARTING STAGE 4 ***
Pairing Confirm response returned from handle: 0
Confirm Value from peer: 0xB0, 0xAB, 0xA2, 0x20, 0x5D, 0x37, 0x62, 0xEF, 0x5D, 0xA4, 0xD7, 0x8A, 0x8B, 0xAF, 0x77, 0xB9

*** STARTING STAGE 5 ***
Generating Na random value for this device as initiator in L2CAP layer...0
DH key generated

*** STARTING STAGE 6 ***
DHK Generated in HCI Layer
DHK Stored as: 0x37, 0x93, 0xC3, 0xE5, 0xB8, 0x4A, 0x3D, 0xD2, 0x40, 0xA, 0x6B, 0x1D, 0xDD, 0x78, 0x60, 0xD7, 0x3B, 0xD8, 0xC7, 0xEB, 0xDB, 0x41, 0xBB, 0x61, 0x20, 0x77, 0x10, 0x83, 0xBC, 0xF9, 0xD9, 0x48
Set Peer encryption : DHK KEY CALCULATEDSending Na random value to peer device in L2CAP layer...HCI.Na value set as: 
0x69, 0xE, 0xEB, 0x4E, 0x43, 0x99, 0x20, 0x47, 0x78, 0x7D, 0xFC, 0x26, 0x5, 0x6F, 0xA4, 0x2E
Sent Na random value to peer device!
handleSecurityData: code: 0x4
rx security:0x4, 0x2E, 0x1, 0xBA, 0x4, 0x12, 0x0, 0x13, 0x5D, 0xA2, 0x4B, 0x4B, 0x0, 0xE8, 0x12, 0x2E, 0x1
*** STARTING STAGE 7 ***
Processing Incoming Random Request Response from peer
Getting Nb random value from peer device in L2CAP layer...HCI.Nb value set as: 
0x1, 0x2E, 0x12, 0xE8, 0x0, 0x4B, 0x4B, 0xA2, 0x5D, 0x13, 0x0, 0x12, 0x4, 0xBA, 0x1, 0x2E
Stored Nb random value from peer device!
U      : 0x6, 0x8B, 0xCD, 0x6C, 0x86, 0x47, 0xA3, 0x20, 0x5F, 0xE5, 0x3B, 0xED, 0xA2, 0x66, 0xE8, 0x65, 0xB5, 0x2D, 0x41, 0x2F, 0x73, 0x90, 0xD3, 0xF9, 0x11, 0x35, 0x3C, 0xFC, 0x8, 0xBC, 0xA9, 0x3A
V      : 0x9F, 0x8B, 0x7F, 0xA6, 0x76, 0xB0, 0xB0, 0xF2, 0x36, 0xF4, 0xB2, 0x4E, 0xA2, 0x5F, 0x34, 0x29, 0x5, 0x2F, 0xC2, 0xE, 0x7, 0x18, 0x19, 0x41, 0x30, 0x3E, 0x6B, 0xF4, 0xCA, 0x4D, 0x9B, 0x78
X      : 0x69, 0xE, 0xEB, 0x4E, 0x43, 0x99, 0x20, 0x47, 0x78, 0x7D, 0xFC, 0x26, 0x5, 0x6F, 0xA4, 0x2E
Y      : 0x1, 0x2E, 0x12, 0xE8, 0x0, 0x4B, 0x4B, 0xA2, 0x5D, 0x13, 0x0, 0x12, 0x4, 0xBA, 0x1, 0x2E
g2res  : 0x2F, 0x35, 0x98, 0xDD
Result : 792041693
localPublicKeyBuffer: 0x3A, 0xA9, 0xBC, 0x8, 0xFC, 0x3C, 0x35, 0x11, 0xF9, 0xD3, 0x90, 0x73, 0x2F, 0x41, 0x2D, 0xB5, 0x65, 0xE8, 0x66, 0xA2, 0xED, 0x3B, 0xE5, 0x5F, 0x20, 0xA3, 0x47, 0x86, 0x6C, 0xCD, 0x8B, 0x6, 0xC1, 0x7, 0x39, 0xB0, 0xE2, 0x41, 0xBE, 0xBA, 0x16, 0x9F, 0xF4, 0x3A, 0xD9, 0x9E, 0x40, 0xA7, 0x11, 0xA5, 0xC7, 0x55, 0x39, 0xD5, 0x7D, 0xD4, 0xF, 0x8F, 0xD3, 0xB3, 0x9B, 0x4F, 0x68, 0xE0
remotePublicKeyBuffer: 0x78, 0x9B, 0x4D, 0xCA, 0xF4, 0x6B, 0x3E, 0x30, 0x41, 0x19, 0x18, 0x7, 0xE, 0xC2, 0x2F, 0x5, 0x29, 0x34, 0x5F, 0xA2, 0x4E, 0xB2, 0xF4, 0x36, 0xF2, 0xB0, 0xB0, 0x76, 0xA6, 0x7F, 0x8B, 0x9F, 0x55, 0xDF, 0x30, 0x6A, 0xFF, 0xA1, 0xBB, 0xDB, 0x17, 0x71, 0x22, 0x41, 0xF2, 0xD1, 0xE1, 0xE7, 0x6B, 0x25, 0xC9, 0x8A, 0x94, 0xA8, 0x6C, 0x65, 0xA0, 0xCD, 0x9A, 0x38, 0xE6, 0xBB, 0x2D, 0x81
Original Confirm Value: 0xB0, 0xAB, 0xA2, 0x20, 0x5D, 0x37, 0x62, 0xEF, 0x5D, 0xA4, 0xD7, 0x8A, 0x8B, 0xAF, 0x77, 0xB9
New Confirm Value: 0xB0, 0xAB, 0xA2, 0x20, 0x5D, 0x37, 0x62, 0xEF, 0x5D, 0xA4, 0xD7, 0x8A, 0x8B, 0xAF, 0x77, 0xB9
Confirm Values match. Sending DHK Check

*** STARTING STAGE 8 ***
Sending DHK Check to Peer in L2CAP Layer
Retrieve local and remote BD addresses
Local Address set as:0x0, 0x8, 0xBC, 0x5A, 0x39, 0xDC, 0xE
Remote Address set as:0x0, 0xA8, 0x8C, 0x3E, 0x16, 0xB3, 0xEB
DHK Value is:0x37, 0x93, 0xC3, 0xE5, 0xB8, 0x4A, 0x3D, 0xD2, 0x40, 0xA, 0x6B, 0x1D, 0xDD, 0x78, 0x60, 0xD7, 0x3B, 0xD8, 0xC7, 0xEB, 0xDB, 0x41, 0xBB, 0x61, 0x20, 0x77, 0x10, 0x83, 0xBC, 0xF9, 0xD9, 0x48
Calculating MacKey and LTK using f5
Starting f5 calculationUsing DHKey:  0x37, 0x93, 0xC3, 0xE5, 0xB8, 0x4A, 0x3D, 0xD2, 0x40, 0xA, 0x6B, 0x1D, 0xDD, 0x78, 0x60, 0xD7, 0x3B, 0xD8, 0xC7, 0xEB, 0xDB, 0x41, 0xBB, 0x61, 0x20, 0x77, 0x10, 0x83, 0xBC, 0xF9, 0xD9, 0x48
Using N_Master: 0x69, 0xE, 0xEB, 0x4E, 0x43, 0x99, 0x20
Using N_Slave:  0x1, 0x2E, 0x12, 0xE8, 0x0, 0x4B, 0x4B
Using BD_ADDR_MASTER: 
0x0, 0x8, 0xBC, 0x5A, 0x39, 0xDC
Using BD_ADDR_SLAVE:  
0x0, 0xA8, 0x8C, 0x3E, 0x16, 0xB3
MAC Key generated as:0xDF, 0xD4, 0x16, 0xD5, 0x9A, 0x62, 0x24, 0x48, 0xAE, 0x1, 0x49, 0x2F, 0xCC, 0xE0, 0xB8, 0x9A
LTK generated as:0x45, 0x66, 0xD6, 0xC1, 0xC4, 0x96, 0xC7, 0x14, 0x77, 0x31, 0x20, 0x13, 0xD5, 0xB2, 0x6D, 0xE
Master IO Cap to use:0x9, 0x0, 0x3
R Value to use:0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
Calculating Ea value using f6 function
Starting f6 calculation DEBUG
Using W:  
0xDF, 0xD4, 0x16, 0xD5, 0x9A, 0x62, 0x24, 0x48, 0xAE, 0x1, 0x49, 0x2F, 0xCC, 0xE0, 0xB8, 0x9A
Using N1: 
0x69, 0xE, 0xEB, 0x4E, 0x43, 0x99, 0x20, 0x47, 0x78, 0x7D, 0xFC, 0x26, 0x5, 0x6F, 0xA4, 0x2E
Using N2:  
0x1, 0x2E, 0x12, 0xE8, 0x0, 0x4B, 0x4B, 0xA2, 0x5D, 0x13, 0x0, 0x12, 0x4, 0xBA, 0x1, 0x2E
Using R:  
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
Using IOCap:  
0x9, 0x0, 0x3
Using A1: 
0x0, 0x8, 0xBC, 0x5A, 0x39, 0xDC, 0xE
Using A2:  
0x0, 0xA8, 0x8C, 0x3E, 0x16, 0xB3, 0xEB
Ea value calulated as:0x66, 0x2A, 0x9, 0x6E, 0xE4, 0xE1, 0x43, 0xFA, 0xA3, 0x5F, 0xF9, 0x8A, 0x80, 0x35, 0xF5, 0xE5
Sending DHK Check request to peer...
DHK Check request sent to peer.
Set Peer Encryption to SENT_DH_CHECK
DHK Check Sent!
handleSecurityData: code: 0x5
rx security:0x5, 0x8
Pairing failed with code: 0x8
PAIRING FAILED --- Set Peer Encryption to NO_ENCRYPTION

Any help would be really appreciated, and hopefully stop me putting a few more dents into my desk :smile:

Kind regards,

Joe CV

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.