cancel
Showing results for 
Search instead for 
Did you mean: 

Out of Band Pairing

~Amit~
Associate III

Hi,

I have a project where we use the STM32WB55 with the ST25R3911B as NFC module for OOB pairing.

I couldn't find any example for OOB pairing flow.

My start point is the p2p_server example and I can see there are:

  • BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.OOB_Data
  • BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.OOB_Data_Present

which I assume are relevant for my cause.

After reading AN5289 I also can tell there are:

  • aci_gap_set_oob_data()
  • aci_gap_get_oob_data() - which in my case always return an array of '0' at the

But I can't figure how to connect the dots. is there any example for OOB?

when I am invoking get oob data as below I always get OOB_Data array of '0', why?

uint8_t Address_Type = 0;

uint8_t Address[6];

// initial value is just for seeing it gets override

uint8_t OOB_Data[16] = { 0x01, 0x02, 0x03 };

uint8_t OOB_Data_Len;

uint8_t getOobDataRes = aci_gap_get_oob_data(0x01, &Address_Type, Address, &OOB_Data_Len, OOB_Data);

If there is no example I would appreciate if you can answer my questions ( a reference to the relevant functions would be awsome! :(

  • when I invoke aci_gap_set_oob_data() what should be the content of OOB_Data argument? I can see it's 16 bytes (which I assume received from outside) but what are thay stand for? is there any standard for it?
  • What is the flow I need to conduct in order to pair a device once I recieved the NDEF via NFC?
  • After the pairing process, If I want them to bond what else is required?
  • After the bonding how can I implement white list such that only the bonded device would be able to connect?

Thanks

1 ACCEPTED SOLUTION

Accepted Solutions
Remi QUINTIN
ST Employee

a) When I invoke aci_gap_set_oob_data() what should be the content of OOB_Data argument? I can see it's 16 bytes (which I assume received from outside) but what are thay stand for? is there any standard for it?

The encryption key to send via OOB data is generated by the controller (low layers of the RF stack running on the M0+ core)

You can get this 16-byte key with the aci_gap_get_oob_data() function. Once you get key, it is up to you to transmit it to the other device over an NFC link.

On the other device, you should call the aci_gap_set_oob_data() function to set up the encryption key.

There is also another way to create the key. You can also generate your own key using the EDCH algoritm and set it as OOB data on both sides of the link. In this case, you have to use aci_gap_set_oob_data() on the Central and on the peripheral device.

See the slide set I joint to this answer.

    

b) What is the flow I need to conduct in order to pair a device once I recieved the NDEF via NFC?

Answer is above and in the slide set.

c) After the pairing process, if I want them to bond what else is required?

Bonding has to be set as a requirement using the aci_gap_set_auth_requirement() function before any connection is created. Set the bonding parameter to 1 so that the bonding happens with the pairing.

    

d) After the bonding how can I implement white list such that only the bonded device would be able to connect?

I do not an example of white list management right now

For your implementation, I recommend you to have a look at application notes AN5270 and AN5289

View solution in original post

14 REPLIES 14
~Amit~
Associate III

Up

Remi QUINTIN
ST Employee

a) When I invoke aci_gap_set_oob_data() what should be the content of OOB_Data argument? I can see it's 16 bytes (which I assume received from outside) but what are thay stand for? is there any standard for it?

The encryption key to send via OOB data is generated by the controller (low layers of the RF stack running on the M0+ core)

You can get this 16-byte key with the aci_gap_get_oob_data() function. Once you get key, it is up to you to transmit it to the other device over an NFC link.

On the other device, you should call the aci_gap_set_oob_data() function to set up the encryption key.

There is also another way to create the key. You can also generate your own key using the EDCH algoritm and set it as OOB data on both sides of the link. In this case, you have to use aci_gap_set_oob_data() on the Central and on the peripheral device.

See the slide set I joint to this answer.

    

b) What is the flow I need to conduct in order to pair a device once I recieved the NDEF via NFC?

Answer is above and in the slide set.

c) After the pairing process, if I want them to bond what else is required?

Bonding has to be set as a requirement using the aci_gap_set_auth_requirement() function before any connection is created. Set the bonding parameter to 1 so that the bonding happens with the pairing.

    

d) After the bonding how can I implement white list such that only the bonded device would be able to connect?

I do not an example of white list management right now

For your implementation, I recommend you to have a look at application notes AN5270 and AN5289

~Amit~
Associate III

Thank you Remi,

I implemented the flow at the presentation yet I don't receive an hci_le_read_local_p256_public_key_complete_event.

I started with the BLE_p2pServer example (FW package 1.7), and added the following lines at the end of APP_BLE_Init():

/* USER CODE BEGIN APP_BLE_Init_2 */

uint8_t mask[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9F };

if (hci_le_set_event_mask(mask)) {

while (1);

}

if (hci_le_read_local_p256_public_key()) {

while (1);

}

/* USER CODE END APP_BLE_Init_2 */

later, I added my own implementation to hci_le_read_local_p256_public_key_complete_event() with the same fuction signature as the weak (just that mine is not weak) but I don't get the event.

any ideas?

Remi QUINTIN
ST Employee

in fact you should initialise the event mask in the following way.

uint8_t ALL_EVENTS[8]={0x9F,0x01,0x00,0x00,0x00,0x00,0x00,0x00};

hci_le_set_event_mask(ALL_EVENTS);

status = hci_le_read_local_p256_public_key();

Then wait for the event:

#define HCI_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE_SUBEVT_CODE 0x08

In the handler: case EVT_LE_META_EVENT:

~Amit~
Associate III

Thank you Remi for the detailed answers! it was very helpful!

I was able to produce the flow and I am succesfully bonding 2 devices, yet I have some uncleared issues:

  1. While reading the presentation, I assumed that each pink/red block is conducted by the controller layer and dosen't require my additional interfering - am I correct?
  2. I couldn't get any hci_command_complete_event. what I did is adding a case of 'HCI_COMMAND_COMPLETE_EVT_CODE' under switch (event_pckt->evt) of SVCCTL_App_Notification(). What am I doing wrong?
  3. Right after bonding, aci_gap_get_bonded_devices() return the bonded device. but, after resetting the device I noticed that aci_gap_get_bonded_devices() returnes 0 devices. should I save myself the bonded devices? if so what additional data I should save for not requiering the pairing each time?
  4. When reaching the stage where the peripheral should be discovered, I want to allow only to known devices which I have their addresses to connect. can I set whitelist when invoking aci_gap_set_discoverable()? do you have any other implemention suggestion?

Remi QUINTIN
ST Employee

1) Yes these are automatic exchanges done at RF stack level with no need for the host to interfere.

2) 'HCI_COMMAND_COMPLETE_EVT_CODE' is returned for any asynchronous HCI command. Now I must admit I did not see this event checked in the current code. Are you able to get the HCI_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE_SUBEVT_CODE?

3) Bonding must be enabled (bonding_mode=1 in the aci_gap_set_authentication_requirement function. Then when the bonding mode is enabled, the list of bonded devices is entirely managed by the controller (on M0+) and saved in Flash memory. So, you should still be able to get the bonded device list after a reset with the aci_gap_get_bonded_devices() function.

4) device address must have been put in the white list with the aci_gap_configure_white_list command. This is to be done after the disconnection. You have to save this white list in Flash memory in order to save it in case of reset.

Then you can use the aci_gap_set_undirected_connectable function that has a filter policy parameter for advertising (0x03: Allow scan request from white list only, allow connect request from white list only).

Remi QUINTIN
ST Employee

I saw another point that you raise and that I did not answer

> What is the reason I need to invoke aci_gap_set_oob_data(zeroes) on each device before getting the oob data? (I noticed that if I am not doing it the aci_gap_get_oob_data() don't work properly and return zeroes).

In fact you have to call the aci_gap_set_oob_data(zeroes) function that enables the generation of the OOB data on the data source device when the input parameter is set to 0. Then aci_gap_get_oob_data() function enables the retrieval of the generated (thanks to aci_gap_set_oob_data(zeroes)) OOB data. This is the reason why it did not work without the aci_gap_set_oob_data(zeroes) call . This OOB data is sent via NFC to the other device that uses the aci_gap_set_oob_data(received OOB_DATA).

Hci_le_read_local_p256_public_key() forces the generation of a new public Key each time it is called. The public keys are exchanged in between the 2 devices via the BLE connection and are used to perform some checks

Commands used to get the generated OOB data on device data source

   Aci_gap_get_oob_data(oob_data_type=0x01-random)

   Random data received through Hci_command_complete_event

  RANDOM_DATA – local pairing data intended to the remote device to be sent via NFC

  Aci_gap_get_oob_data(oob_data_type=0x02-confirm)

  Random data received through Hci_command_complete_event

  CONFIRM_DATA – local pairing data intended to the remote device to be sent via NFC

These 2 values are used with the Public keys by each device to perform some verifications.

To get those oob data, you can do it this way:

 uint8_t at = 0;

uint8_t len = 0;

 uint8_t rand[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

 uint8_t hash[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

/* Get own OOB data from device data source */

  status = aci_gap_get_oob_data(1, &at,add,&len, rand);

  status = aci_gap_get_oob_data(2, &at,add,&len, hash);

Thanks Remi

  1. Great
  2. I am able to get the HCI_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE_SUBEVT_CODE but not the HCI_COMMAND_COMPLETE_EVT_CODE. this led me to a workaround of invoking aci_gap_get_oob_data and then start polling the value of OOB_Data until it has been changed. this is not a proper solution, is there a way to get an event?
  3. The bonding is enabled by BleApplicationContext.BleApplicationContext_legacy.bleSecurityParam.bonding_mode = CFG_BONDING_MODE; when CFG_BONDING_MODE is defined as 1. after the mentioned setting aci_gap_set_authentication_requirement is invoked with the relevant args. I am able to pair and bond. I invoke aci_gap_get_bonded_devices() periodically and I can see I got the remote device as bonded after bonding. the issue is that after a reset, aci_gap_get_bonded_devices() returns no bonded devices. more precisely Num_of_Addresses value is 0. I tried (not sure it should affect) setting CFG_HW_RESET_BY_FW to 0 but it didn't help. what should I do?
  4. OK. this sounds exactly what I need but the aci_gap_configure_whitelist() doesn't take any arguments so how do I insert the allowed addresses into the whitelist? also, I didn't understand the part it has to be done after the disconnection, can you please explain?

It's clear now - much appriciated.