2020-06-18 05:09 AM
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:
which I assume are relevant for my cause.
After reading AN5289 I also can tell there are:
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! :(
Thanks
Solved! Go to Solution.
2020-06-23 03:02 PM
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
2020-06-22 01:23 PM
Up
2020-06-23 03:02 PM
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
2020-06-24 10:32 AM
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?
2020-06-26 01:42 AM
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:
2020-07-01 11:45 PM
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:
2020-07-03 08:36 AM
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).
2020-07-03 09:32 AM
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);
2020-07-07 03:26 AM
Thanks Remi
2020-07-07 03:28 AM
It's clear now - much appriciated.