Skip to content

Commit

Permalink
bluetooth: Support BLE pairing
Browse files Browse the repository at this point in the history
Add BLE pairing API.
  • Loading branch information
SPRESENSE committed Mar 7, 2023
1 parent 466ecc0 commit b76b093
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 58 deletions.
50 changes: 49 additions & 1 deletion sdk/modules/bluetooth/bluetooth_common.c
@@ -1,7 +1,7 @@
/****************************************************************************
* modules/bluetooth/bluetooth_common.c
*
* Copyright 2018 Sony Semiconductor Solutions Corporation
* Copyright 2018, 2023 Sony Semiconductor Solutions Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -339,6 +339,24 @@ static int ble_event_load_bond(struct ble_event_bondinfo_t *evt)
return ret;
}

static int ble_event_encryption_result(struct ble_event_encryption_result_t *evt)
{
int ret = BT_SUCCESS;
struct ble_common_ops_s *ops = g_bt_common_state.ble_common_ops;

if (ops && ops->encryption_result)
{
ops->encryption_result(evt->conn_handle, evt->result);
}
else
{
_err("%s [BLE][Common] callback not registered.\n", __func__);
return BT_FAIL;
}

return ret;
}

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -1063,6 +1081,33 @@ int ble_disconnect(struct ble_state_s *ble_state)
return ret;
}

/****************************************************************************
* Name: ble_pairing
*
* Description:
* Bluetooth LE pairing for Central
* This function is for Central role.
*
****************************************************************************/

int ble_pairing(uint16_t conn_handle)
{
int ret = BT_SUCCESS;
struct ble_hal_common_ops_s *ops = g_bt_common_state.ble_hal_common_ops;

if (ops && ops->pairing)
{
ret = ops->pairing(conn_handle);
}
else
{
_err("%s [BLE][Common] not supported.\n", __func__);
return BT_FAIL;
}

return ret;
}

/****************************************************************************
* Name: ble_start_advertise
*
Expand Down Expand Up @@ -1300,6 +1345,9 @@ int ble_common_event_handler(struct bt_event_t *bt_event)
case BLE_COMMON_EVENT_LOAD_BOND:
return ble_event_load_bond((struct ble_event_bondinfo_t *) bt_event);

case BLE_COMMON_EVENT_ENCRYPTION_RESULT:
return ble_event_encryption_result((struct ble_event_encryption_result_t *) bt_event);

default:
break;
}
Expand Down
149 changes: 142 additions & 7 deletions sdk/modules/bluetooth/hal/nrf52/ble_comm.c
Expand Up @@ -149,6 +149,7 @@ static int nrf52_ble_set_ppcp(BLE_CONN_PARAMS ppcp);
static uint16_t nrf52_ble_set_mtusize(uint16_t sz);
static uint16_t nrf52_ble_get_mtusize(void);
static int nrf52_ble_get_negotiated_mtusize(uint16_t handle);
static int nrf52_ble_pairing(uint16_t handle);

static int nrf52_bt_init(void);
static int nrf52_bt_finalize(void);
Expand Down Expand Up @@ -189,6 +190,7 @@ static struct ble_hal_common_ops_s ble_hal_common_ops =
.setMtuSize = nrf52_ble_set_mtusize,
.getMtuSize = nrf52_ble_get_mtusize,
.getNegotiatedMtuSize = nrf52_ble_get_negotiated_mtusize,
.pairing = nrf52_ble_pairing,
};

static struct bt_hal_common_ops_s bt_hal_common_ops =
Expand Down Expand Up @@ -843,6 +845,7 @@ static void on_connected(const BLE_EvtConnected* evt)
g_ble_context.conn_sts = BLE_CONN_STS_CONNECTED;
g_ble_context.is_scanning = false;
g_ble_context.is_advertising = false;
memcpy(g_ble_context.ble_addr.addr, evt->addr.addr, BT_ADDR_LEN);

conn_stat_evt.connected = true;
conn_stat_evt.handle = evt->handle;
Expand Down Expand Up @@ -905,8 +908,20 @@ static void on_read_rsp(BLE_EvtGattcRead *readRsp)

static void on_exchange_feature(const BLE_EvtExchangeFeature* exchange_feature)
{
BLE_GapPairingFeature* pf = &g_ble_context.pairing_feature;
int ret = BLE_GapExchangePairingFeature(exchange_feature->handle, pf);
int ret;
BLE_GapPairingFeature* pf = NULL;

/* In central case, pairing feature must not be set,
* because it is transmitted in the parameter of
* preceding sd_ble_gap_authenticate()
*/

if (g_ble_context.ble_role == BLE_ROLE_PERIPHERAL)
{
pf = &g_ble_context.pairing_feature;
}

ret = BLE_GapExchangePairingFeature(exchange_feature->handle, pf);

if (BLE_SUCCESS != ret)
{
Expand All @@ -928,6 +943,18 @@ static void on_disp_passkey(BLE_EvtDisplayPasskey* disp_passkey)
LOG_OUT("[BLE][LOG]Passkey: %s\n", disp_passkey->passkey);
}

static void mk_encryption_result_event(uint16_t handle, bool result)
{
struct ble_event_encryption_result_t evt;

evt.group_id = BLE_GROUP_COMMON;
evt.event_id = BLE_COMMON_EVENT_ENCRYPTION_RESULT;
evt.conn_handle = handle;
evt.result = result;

ble_common_event_handler((struct bt_event_t *) &evt);
}

static void on_auth_status(BLE_EvtAuthStatus* auth_status)
{
int ret = BLE_SUCCESS;
Expand All @@ -936,6 +963,7 @@ static void on_auth_status(BLE_EvtAuthStatus* auth_status)
if (auth_status->status != BLE_GAP_SM_STATUS_SUCCESS)
{
LOG_OUT("[BLE][LOG]Pairing failed! ErrCode: %x\n", auth_status->status);
mk_encryption_result_event(auth_status->handle, false);
return;
}
else
Expand Down Expand Up @@ -1712,16 +1740,93 @@ void onAuthKeyRequest(BLE_Evt *pBleEvent, ble_evt_t *pBleNrfEvt)
on_auth_key_request((BLE_EvtAuthKey *)pBleEvent->evtData);
}

static int getAddrFmConnHandle(uint16_t handle, BT_ADDR *addr)
{
if (handle != g_ble_context.ble_conn_handle)
{
/* Invalid connection handle. */

return -EINVAL;
}

memcpy(addr->address, g_ble_context.ble_addr.addr, BT_ADDR_LEN);

return BT_SUCCESS;
}

static int searchBondInfoIndexFmConnHandle(uint16_t handle)
{
int i;
int ret;
uint32_t list = bleBondEnableList;
BT_ADDR addr;

ret = getAddrFmConnHandle(handle, &addr);
if (ret != BT_SUCCESS)
{
return ret;
}

for (i = 0; i < BLE_SAVE_BOND_DEVICE_MAX_NUM; i++, list >>= 1)
{
if (list & 1)
{
if (memcmp(addr.address,
BondInfoInFlash[i].bondInfo.addr,
BT_ADDR_LEN)
== 0)
{
break;
}
}
}

return i;
}

static void clearBondInfo(uint16_t handle)
{
int ret;

ret = searchBondInfoIndexFmConnHandle(handle);
printf("searchBondInfoIndexFmConnHandle ret = %d\n", ret);
if ((ret >= 0) && (ret < BLE_SAVE_BOND_DEVICE_MAX_NUM))
{
memset(&BondInfoInFlash[ret], 0, sizeof(bleGapWrapperBondInfo));
bleBondEnableList &= ~(1 << ret);
mk_save_bondinfo_event();
}
}

static
void onConnSecUpdate(BLE_Evt *pBleEvent, ble_evt_t *pBleNrfEvt)
{
bool result;
ble_gap_evt_t *evt = &pBleNrfEvt->evt.gap_evt;
ble_gap_conn_sec_t *prm = &evt->params.conn_sec_update.conn_sec;

pBleEvent->evtHeader = BLE_GAP_EVENT_CONN_SEC_UPDATE;
pBleEvent->evtDataSize = 0;
#ifdef BLE_DBGPRT_ENABLE
ble_gap_evt_conn_sec_update_t *sec = &pBleNrfEvt->evt.gap_evt.params.conn_sec_update;
BLE_PRT("onConnSecUpdate: keysize=%d sm=%d lv=%d\n", sec->conn_sec.encr_key_size,
sec->conn_sec.sec_mode.sm, sec->conn_sec.sec_mode.lv);
#endif
BLE_PRT("onConnSecUpdate: keysize=%d sm=%d lv=%d\n", prm->encr_key_size,
prm->sec_mode.sm, prm->sec_mode.lv);

if (prm->encr_key_size > 0)
{
/* Positive key size means that the connection is encrypted. */

result = true;
}
else
{
/* Non-positive key size means that encryption fails.
* In such a case, the corresponding bond information shall be cleared.
*/

clearBondInfo(evt->conn_handle);
result = false;
}

mk_encryption_result_event(evt->conn_handle, result);
}

static
Expand Down Expand Up @@ -2959,6 +3064,36 @@ static int nrf52_ble_get_negotiated_mtusize(uint16_t handle)
return commMem.client_rx_mtu;
}


static int nrf52_ble_pairing(uint16_t handle)
{
int ret;

ret = searchBondInfoIndexFmConnHandle(handle);
if (ret < 0)
{
/* Invalid handle error */

return ret;
}
else if (ret < BLE_SAVE_BOND_DEVICE_MAX_NUM)
{
/* If pairing information about this connection is stored,
* skip pairing and only encrypt with stored key.
*/

ret = BLE_GapEncrypt(handle, &BondInfoInFlash[ret].peerEncKey);
}
else
{
/* Otherwise, execute pairing. */

ret = BLE_GapAuthenticate(handle, &g_ble_context.pairing_feature);
}

return ret;
}

/****************************************************************************
* Public Data
****************************************************************************/
Expand Down
82 changes: 33 additions & 49 deletions sdk/modules/bluetooth/hal/nrf52/ble_gap.c
Expand Up @@ -418,37 +418,38 @@ int BLE_GapExchangePairingFeature(BLE_GapConnHandle connHandle, BLE_GapPairingFe
int errCode = 0;
ble_gap_sec_params_t secParams = {0};
ble_gap_sec_keyset_t keysExchanged = {{0}};
ble_gap_sec_params_t *p_sec = NULL;

if(pairingFeature == NULL) {
BLE_PRT("pairingFeature is NULL!!!\n");
return -EINVAL;
}
if((pairingFeature->oob != BLE_GAP_OOB_AUTH_DATA_PRESENT) &&
(pairingFeature->oob != BLE_GAP_OOB_AUTH_DATA_NOT_PRESENT)) {
BLE_PRT("pairingFeature->oob=%d\n", pairingFeature->oob);
return -EINVAL;
}
if((pairingFeature->maxKeySize < pairingFeature->minKeySize) ||
(pairingFeature->maxKeySize > BLE_GAP_MAX_KEY_SIZE) ||
(pairingFeature->minKeySize < BLE_GAP_MIN_KEY_SIZE)) {
BLE_PRT("pairingFeature->maxKeySize=%d, pairingFeature->minKeySize=%d\n", pairingFeature->maxKeySize, pairingFeature->minKeySize);
return -EINVAL;
}
if(pairingFeature != NULL) {
if((pairingFeature->oob != BLE_GAP_OOB_AUTH_DATA_PRESENT) &&
(pairingFeature->oob != BLE_GAP_OOB_AUTH_DATA_NOT_PRESENT)) {
BLE_PRT("pairingFeature->oob=%d\n", pairingFeature->oob);
return -EINVAL;
}
if((pairingFeature->maxKeySize < pairingFeature->minKeySize) ||
(pairingFeature->maxKeySize > BLE_GAP_MAX_KEY_SIZE) ||
(pairingFeature->minKeySize < BLE_GAP_MIN_KEY_SIZE)) {
BLE_PRT("pairingFeature->maxKeySize=%d, pairingFeature->minKeySize=%d\n", pairingFeature->maxKeySize, pairingFeature->minKeySize);
return -EINVAL;
}

memset(&secParams,0,sizeof(secParams));
memset(&keysExchanged,0,sizeof(keysExchanged));
memset(&secParams,0,sizeof(secParams));
memset(&keysExchanged,0,sizeof(keysExchanged));

memset(&gapMem.wrapperBondInfo.ownEncKey,0,sizeof(gapMem.wrapperBondInfo.ownEncKey));
memset(&gapMem.wrapperBondInfo.ownIdKey,0,sizeof(gapMem.wrapperBondInfo.ownIdKey));
memset(&gapMem.wrapperBondInfo.peerEncKey,0,sizeof(gapMem.wrapperBondInfo.peerEncKey));
memset(&gapMem.wrapperBondInfo.peerIdKey,0,sizeof(gapMem.wrapperBondInfo.peerIdKey));
memset(&gapMem.wrapperBondInfo.ownEncKey,0,sizeof(gapMem.wrapperBondInfo.ownEncKey));
memset(&gapMem.wrapperBondInfo.ownIdKey,0,sizeof(gapMem.wrapperBondInfo.ownIdKey));
memset(&gapMem.wrapperBondInfo.peerEncKey,0,sizeof(gapMem.wrapperBondInfo.peerEncKey));
memset(&gapMem.wrapperBondInfo.peerIdKey,0,sizeof(gapMem.wrapperBondInfo.peerIdKey));

secParams.oob = pairingFeature->oob;
secParams.io_caps = pairingFeature->ioCap;
secParams.max_key_size = pairingFeature->maxKeySize;
secParams.min_key_size = pairingFeature->minKeySize;
secParams.mitm = (pairingFeature->authReq & BLE_GAP_AUTH_MITM) >> 1;
secParams.bond = (pairingFeature->authReq & BLE_GAP_AUTH_BOND) >> 0;
secParams.oob = pairingFeature->oob;
secParams.io_caps = pairingFeature->ioCap;
secParams.max_key_size = pairingFeature->maxKeySize;
secParams.min_key_size = pairingFeature->minKeySize;
secParams.mitm = (pairingFeature->authReq & BLE_GAP_AUTH_MITM) >> 1;
secParams.bond = (pairingFeature->authReq & BLE_GAP_AUTH_BOND) >> 0;

p_sec = &secParams;
}

secParams.kdist_own.enc = 1;
secParams.kdist_own.id = 1;
Expand All @@ -460,7 +461,7 @@ int BLE_GapExchangePairingFeature(BLE_GapConnHandle connHandle, BLE_GapPairingFe
keysExchanged.keys_peer.p_enc_key = &gapMem.wrapperBondInfo.peerEncKey;
keysExchanged.keys_peer.p_id_key = &gapMem.wrapperBondInfo.peerIdKey;

errCode = sd_ble_gap_sec_params_reply(connHandle, BLE_GAP_SEC_STATUS_SUCCESS, &secParams, &keysExchanged);
errCode = sd_ble_gap_sec_params_reply(connHandle, BLE_GAP_SEC_STATUS_SUCCESS, p_sec, &keysExchanged);
ret = bleConvertErrorCode((uint32_t)errCode);
memcpy(&gapMem.keySet, &keysExchanged, sizeof(ble_gap_sec_keyset_t));
#ifdef BLE_DBGPRT_ENABLE
Expand Down Expand Up @@ -914,28 +915,11 @@ int BLE_GapGetBondInfoIdList(BLE_GapBondInfoList *bondInfo)
return 0;
}

int BLE_GapEncrypt(BLE_GapConnHandle connHandle)
int BLE_GapEncrypt(uint16_t handle, ble_gap_enc_key_t *key)
{
int index;
uint32_t list = bleBondEnableList;
int errCode = 0;
if (gapMem.is_connected) {
for(index = 0; index < BLE_SAVE_BOND_DEVICE_MAX_NUM; index++, list >>= 1) {
if (!(list & 1)) {
continue;
}
if (BondInfoInFlash[index].bondInfo.addrType != gapMem.wrapperBondInfo.bondInfo.addrType) {
continue;
}
if(!memcmp(BondInfoInFlash[index].bondInfo.addr,
gapMem.wrapperBondInfo.bondInfo.addr, BLE_GAP_ADDR_LENGTH)) {
gapMem.wrapperBondInfo = BondInfoInFlash[index];
break;
}
}
}
errCode = sd_ble_gap_encrypt(connHandle,
&gapMem.wrapperBondInfo.peerEncKey.master_id, &gapMem.wrapperBondInfo.peerEncKey.enc_info);
int errCode;

errCode = sd_ble_gap_encrypt(handle, &key->master_id, &key->enc_info);
return bleConvertErrorCode((uint32_t)errCode);
}

Expand Down

0 comments on commit b76b093

Please sign in to comment.