Hi all,
in my project I want to import a bonding on to the CC26x2 device. The CC26x2 shall be a central device and resolve RPAs of undirected scannable advertisements. I can read out the Identity Adress and IRK of the pairing, where I want to substitute the central device.
For this, in accordance with the User Guides Bond Manager Import Bonding Information and Privacy sections, I use the gapBondMgrImportBond() function, in combination the White List Sync option GAPBOND_AUTO_SYNC_WL actiated and with the filter policy SCAN_PARAM_FLT_POLICY set to SCAN_FLT_POLICY_WL as seen below.
For a minimal example which I couldn't get to work the code below is inserted in the simple_central example project in the simple_central.c file in the GAP_DEVICE_INIT_DONE_EVENT switch case of the SimpleCentral_processGapMsg function.
uint8_t result_t;
temp8 = SCAN_FLT_POLICY_WL;
result_t = GapScan_setParam(SCAN_PARAM_FLT_POLICY, &temp8);
if (result_t == SUCCESS)
{
Display_printf(dispHandle, 30, 0, "SCAN_FLT_POLICY_WL SET SUCCESS",
NULL);
}
else
{
Display_printf(dispHandle, 30, 0, "SCAN_FLT_POLICY_WL SET FAIL",
NULL);
}
uint8_t sync_WL = TRUE;
result_t = GAPBondMgr_SetParameter(GAPBOND_AUTO_SYNC_WL,
sizeof(uint8_t), &sync_WL);
if (result_t == SUCCESS)
{
Display_printf(dispHandle, 31, 0,
"GAPBOND_AUTO_SYNC_WL SET SUCCESS", NULL);
}
else
{
Display_printf(dispHandle, 31, 0, "GAPBOND_AUTO_SYNC_WL SET FAIL",
NULL);
}
// Import Bonding
// Parameters needed for storing bonding information.
gapBondRec_t pSavedBondRec;
gapBondLTK_t pLocalLtk;
gapBondLTK_t pPeerLtk;
uint8_t pPeerIRK[KEYLEN];
uint8_t pPeerSRK[KEYLEN];
uint32_t pPeerSignCount;
gapBondCharCfg_t charCfg;
// pSavedBondRec.addr[0] = 0xF4;
// pSavedBondRec.addr[1] = 0x60;
// pSavedBondRec.addr[2] = 0x77;
// pSavedBondRec.addr[3] = 0x83;
// pSavedBondRec.addr[4] = 0x28;
// pSavedBondRec.addr[5] = 0xCC;
pSavedBondRec.addr[5] = 0xF4;
pSavedBondRec.addr[4] = 0x60;
pSavedBondRec.addr[3] = 0x77;
pSavedBondRec.addr[2] = 0x83;
pSavedBondRec.addr[1] = 0x28;
pSavedBondRec.addr[0] = 0xCC;
pSavedBondRec.addrType = PEER_ADDRTYPE_RANDOM_OR_RANDOM_ID;
pSavedBondRec.stateFlags = 0x1c;
pPeerIRK[0] = 0x16;
pPeerIRK[1] = 0x2B;
pPeerIRK[2] = 0xF4;
pPeerIRK[3] = 0x1B;
pPeerIRK[4] = 0x23;
pPeerIRK[5] = 0x15;
pPeerIRK[6] = 0xC3;
pPeerIRK[7] = 0xED;
pPeerIRK[8] = 0xE2;
pPeerIRK[9] = 0x08;
pPeerIRK[10] = 0x7A;
pPeerIRK[11] = 0xA5;
pPeerIRK[12] = 0xF2;
pPeerIRK[13] = 0x09;
pPeerIRK[14] = 0x83;
pPeerIRK[15] = 0xC5;
// pPeerIRK[15]= 0x16;
// pPeerIRK[14]= 0x2B;
// pPeerIRK[13]= 0xF4;
// pPeerIRK[12]= 0x1B;
// pPeerIRK[11]= 0x23;
// pPeerIRK[10]= 0x15;
// pPeerIRK[9]= 0xC3;
// pPeerIRK[8]= 0xED;
// pPeerIRK[7]= 0xE2;
// pPeerIRK[6]= 0x08;
// pPeerIRK[5]= 0x7A;
// pPeerIRK[4]= 0xA5;
// pPeerIRK[3]= 0xF2;
// pPeerIRK[2]= 0x09;
// pPeerIRK[1]= 0x83;
// pPeerIRK[0]= 0xC5;
pLocalLtk.div = 0;
pLocalLtk.keySize = 0x10;
pPeerLtk.div = 0;
pPeerLtk.keySize = 0x10;
uint8_t i;
for (i = 0; i < B_RANDOM_NUM_SIZE; i++)
{
pLocalLtk.rand[i] = 0;
pPeerLtk.rand[i] = 0;
}
for (i = 0; i < KEYLEN; i++)
{
pPeerSRK[i] = 0;
pPeerLtk.LTK[i] = 0xFF;
pLocalLtk.LTK[i] = 0xFF;
}
pPeerSignCount = 0;
charCfg.attrHandle = 0xffff;
charCfg.value = 0xff;
result_t = gapBondMgrImportBond(&pSavedBondRec, &pLocalLtk, &pPeerLtk,
pPeerIRK, pPeerSRK, pPeerSignCount,
&charCfg);
if (result_t == SUCCESS)
{
Display_printf(dispHandle, 32, 0, "BOND IMPORT SUCCESS", NULL);
}
else
{
Display_printf(dispHandle, 32, 0, "BOND IMPORT FAIL", NULL);
}
The hardcoded address and IRK are taken from a slightly modified simple peripheral example project where in the function SimplePeripheral_updateRPA, additionally the IRK is read out with the function GAP_GetIRK() as seen below.
static void SimplePeripheral_updateRPA(void)
{
uint8_t* pRpaNew;
uint8_t* pDevIDNew;
uint8_t* pDevIRK;
// Read the current RPA.
pRpaNew = GAP_GetDevAddress(FALSE);
pDevIDNew = GAP_GetDevAddress(TRUE);
pDevIRK = GAP_GetIRK();
if (memcmp(pRpaNew, rpa, B_ADDR_LEN))
{
// If the RPA has changed, update the display
Display_printf(dispHandle, SP_ROW_RPA, 0, "RP Addr: %s",
Util_convertBdAddr2Str(pRpaNew));
memcpy(rpa, pRpaNew, B_ADDR_LEN);
Display_printf(dispHandle, SP_ROW_RPA + 5, 0, "ID Addr: %s",
Util_convertBdAddr2Str(pDevIDNew));
Display_printf(dispHandle, SP_ROW_RPA + 6, 0, "IRK: %s",
Util_convertIKR2Str(pDevIRK));
}
}
#define IRKLENGTH 16
char *Util_convertIKR2Str(uint8_t *pAddr)
{
uint8_t charCnt;
char hex[] = "0123456789ABCDEF";
static char str[(2*IRKLENGTH)+3];
char *pStr = str;
*pStr++ = '0';
*pStr++ = 'x';
// Start from end of addr
pAddr += IRKLENGTH;
for (charCnt = IRKLENGTH; charCnt > 0; charCnt--)
{
*pStr++ = hex[*--pAddr >> 4];
*pStr++ = hex[*pAddr & 0x0F];
}
#ifdef FREERTOS
pStr = NULL;
#else
*pStr = 0;
#endif
return str;
}
This produces the following serial output:
The ID Addr and IRK are then hardcoded into the Bonding Import process of simple central device as seen above.
Unfortunately the central device cannot find any peripherals with the filter policy set as described above as seen below:
Where do you see potential issues with my approach? The issue should be very easily reproducible.
A few additional remarks:
- The endianess of IRK and B_ADDR can be rule out as I tried out all combinations of big and little endian.
- If I disable the filter policy the advertisment report can be found.
- When I read out the previoulsly imported Bonding right after importing it as described in the BLE5 User guide as seen below I can see that the import was successful
// Parameters needed for storing bonding information. gapBondRec_t pSavedBondRec1; gapBondLTK_t pLocalLtk1; gapBondLTK_t pPeerLtk1; uint8_t pPeerIRK1[KEYLEN]; uint8_t pPeerSRK1[KEYLEN]; uint32_t pPeerSignCount1; gapBondCharCfg_t charCfg1; uint8_t readStatus = FAILURE; readStatus = gapBondMgrReadBondRec(PEER_ADDRTYPE_RANDOM_OR_RANDOM_ID, pSavedBondRec.addr, &pSavedBondRec1, &pLocalLtk1, &pPeerLtk1, pPeerIRK1, pPeerSRK1, pPeerSignCount1, &charCfg1); if (readStatus == SUCCESS) { // If read success, then export the data // Here we will print it out for later use. // For the print, we added the following defines // Please consider your own example and modify as needed #define SP_ROW_DEBUG_BondLog (TBM_ROW_APP + 9) #define SP_ROW_DEBUG_PeerAddr (TBM_ROW_APP + 10) #define SP_ROW_DEBUG_LocalLTK (TBM_ROW_APP + 16) #define SP_ROW_DEBUG_PeerIRK (TBM_ROW_APP + 40) #define SP_ROW_DEBUG_PeerSRK (TBM_ROW_APP + 56) Display_printf(dispHandle, SP_ROW_DEBUG_PeerAddr, 0, "Peer Device Addr = [0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x];", pSavedBondRec1.addr[0], pSavedBondRec1.addr[1], pSavedBondRec1.addr[2], pSavedBondRec1.addr[3], pSavedBondRec1.addr[4], pSavedBondRec1.addr[5]); Display_printf(dispHandle, SP_ROW_DEBUG_PeerAddr+1, 0, "Peer Device AddrType = 0x%02x; stateFlag = 0x%02x;",pSavedBondRec1.addrType,pSavedBondRec1.stateFlags); Display_printf(dispHandle, SP_ROW_DEBUG_PeerAddr+2, 0, "Local Device eDiv = 0x%02x; keySize = 0x%02x", pLocalLtk1.div, pLocalLtk1.keySize); Display_printf(dispHandle, SP_ROW_DEBUG_PeerAddr+3, 0, "peer Device SignCount = 0x%08x;", pPeerSignCount1); for (i = 0; i < KEYLEN; i++) { Display_printf(dispHandle, SP_ROW_DEBUG_LocalLTK+i, 0, "Local Device LTK[%d]= 0x%02x;", i, pLocalLtk1.LTK[i]); Display_printf(dispHandle, SP_ROW_DEBUG_PeerIRK+i, 0, "Peer Device IRK[%d]= 0x%02x;", i, pPeerIRK1[i]); Display_printf(dispHandle, SP_ROW_DEBUG_PeerSRK+i, 0, "Peer Device SRK[%d]= 0x%02x;", i, pPeerSRK1[i]); } for (i = 0; i < B_RANDOM_NUM_SIZE; i++) { Display_printf(dispHandle, SP_ROW_DEBUG_LocalLTK+16+i, 0, "Local Device rand[%d]= 0x%02x;", i, pLocalLtk1.rand[i]); } Display_printf(dispHandle, SP_ROW_DEBUG_PeerSRK+16+1, 0, "Charcfg attrHandle = 0x%04x; value = 0x%02x", charCfg1.attrHandle, charCfg1.value); }
Thank you very much for your support!