Bluetooth: smp: Add LE SC OOB support for central side

Add support for LE secure connections using OOB authentication for the
central role.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2019-05-28 13:22:40 +02:00 committed by Carles Cufí
commit f8b7f2ab6a

View file

@ -2765,6 +2765,11 @@ static u8_t compute_and_send_master_dhcheck(struct bt_smp *smp)
case PASSKEY_INPUT:
memcpy(r, &smp->passkey, sizeof(smp->passkey));
break;
case LE_SC_OOB:
if (smp->oobd_remote) {
memcpy(r, smp->oobd_remote->r, sizeof(r));
}
break;
default:
return BT_SMP_ERR_UNSPECIFIED;
}
@ -2923,6 +2928,8 @@ static u8_t sc_smp_check_confirm(struct bt_smp *smp)
u8_t r;
switch (smp->method) {
case LE_SC_OOB:
return 0;
case PASSKEY_CONFIRM:
case JUST_WORKS:
r = 0U;
@ -2970,7 +2977,6 @@ static bool le_sc_oob_data_rsp_check(struct bt_smp *smp)
return ((rsp->oob_flag & BT_SMP_OOB_DATA_MASK) == BT_SMP_OOB_PRESENT);
}
#if defined(CONFIG_BT_PERIPHERAL)
static void le_sc_oob_config_set(struct bt_smp *smp,
struct bt_conn_oob_info *info)
{
@ -2978,7 +2984,17 @@ static void le_sc_oob_config_set(struct bt_smp *smp,
bool rsp_oob_present = le_sc_oob_data_rsp_check(smp);
int oob_config = BT_CONN_OOB_NO_DATA;
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
oob_config = req_oob_present ? BT_CONN_OOB_REMOTE_ONLY :
BT_CONN_OOB_NO_DATA;
if (rsp_oob_present) {
oob_config = (oob_config == BT_CONN_OOB_REMOTE_ONLY) ?
BT_CONN_OOB_BOTH_PEERS :
BT_CONN_OOB_LOCAL_ONLY;
}
} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
oob_config = req_oob_present ? BT_CONN_OOB_LOCAL_ONLY :
BT_CONN_OOB_NO_DATA;
@ -2991,7 +3007,6 @@ static void le_sc_oob_config_set(struct bt_smp *smp,
info->lesc.oob_config = oob_config;
}
#endif
static u8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
{
@ -3030,6 +3045,8 @@ static u8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
return 0;
case JUST_WORKS:
break;
case LE_SC_OOB:
break;
case PASSKEY_DISPLAY:
case PASSKEY_INPUT:
smp->passkey_round++;
@ -3505,6 +3522,31 @@ static u8_t smp_public_key(struct bt_smp *smp, struct net_buf *buf)
atomic_set_bit(smp->flags, SMP_FLAG_USER);
bt_auth->passkey_entry(smp->chan.chan.conn);
break;
case LE_SC_OOB:
/* Step 6: Select random N */
if (bt_rand(smp->prnd, 16)) {
return BT_SMP_ERR_UNSPECIFIED;
}
if (bt_auth->oob_data_request) {
struct bt_conn_oob_info info = {
.type = BT_CONN_OOB_LE_SC,
.lesc.oob_config = BT_CONN_OOB_NO_DATA,
};
le_sc_oob_config_set(smp, &info);
smp->oobd_local = NULL;
smp->oobd_remote = NULL;
atomic_set_bit(smp->flags,
SMP_FLAG_OOB_PENDING);
bt_auth->oob_data_request(smp->chan.chan.conn,
&info);
} else {
return BT_SMP_ERR_UNSPECIFIED;
}
break;
default:
return BT_SMP_ERR_UNSPECIFIED;
}
@ -3548,6 +3590,11 @@ static u8_t smp_dhkey_check(struct bt_smp *smp, struct net_buf *buf)
case PASSKEY_INPUT:
memcpy(r, &smp->passkey, sizeof(smp->passkey));
break;
case LE_SC_OOB:
if (smp->oobd_local) {
memcpy(r, smp->oobd_local->r, sizeof(r));
}
break;
default:
return BT_SMP_ERR_UNSPECIFIED;
}
@ -4491,7 +4538,13 @@ static bool le_sc_oob_data_check(struct bt_smp *smp, bool oobd_local_present,
bool req_oob_present = le_sc_oob_data_req_check(smp);
bool rsp_oob_present = le_sc_oob_data_rsp_check(smp);
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
if ((req_oob_present != oobd_remote_present) &&
(rsp_oob_present != oobd_local_present)) {
return false;
}
} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
if ((req_oob_present != oobd_local_present) &&
(rsp_oob_present != oobd_remote_present)) {
return false;
@ -4512,23 +4565,24 @@ static int le_sc_oob_pairing_continue(struct bt_smp *smp)
return err;
}
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
bool match = (memcmp(c, smp->oobd_remote->c,
sizeof(c)) == 0);
bool match = (memcmp(c, smp->oobd_remote->c, sizeof(c)) == 0);
if (!match) {
smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
return 0;
}
if (!match) {
smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
return 0;
}
}
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
smp_send_pairing_random(smp);
}
smp_send_pairing_random(smp);
return 0;
}