Bluetooth: Add support for confirming incoming JustWorks pairing
If incoming pairing request would result in JustWorks pairing this can be used to request consent from user for accepting it. Change-Id: If0695d0e1bb010bade6a16abe1b57a2ce07856cc Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
This commit is contained in:
parent
931afc81a4
commit
c2a1ac8ae7
5 changed files with 153 additions and 13 deletions
|
@ -354,6 +354,11 @@ int bt_conn_auth_passkey_confirm(struct bt_conn *conn)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bt_conn_auth_pairing_confirm(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Connection related events */
|
/* Connection related events */
|
||||||
|
|
||||||
static void notify_connected(struct bt_conn *conn)
|
static void notify_connected(struct bt_conn *conn)
|
||||||
|
|
|
@ -315,6 +315,7 @@ struct bt_conn_auth_cb {
|
||||||
void (*passkey_entry)(struct bt_conn *conn);
|
void (*passkey_entry)(struct bt_conn *conn);
|
||||||
void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey);
|
void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey);
|
||||||
void (*cancel)(struct bt_conn *conn);
|
void (*cancel)(struct bt_conn *conn);
|
||||||
|
void (*pairing_confirm)(struct bt_conn *conn);
|
||||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||||
void (*pincode_entry)(struct bt_conn *conn, bool highsec);
|
void (*pincode_entry)(struct bt_conn *conn, bool highsec);
|
||||||
#endif
|
#endif
|
||||||
|
@ -364,6 +365,17 @@ int bt_conn_auth_cancel(struct bt_conn *conn);
|
||||||
*/
|
*/
|
||||||
int bt_conn_auth_passkey_confirm(struct bt_conn *conn);
|
int bt_conn_auth_passkey_confirm(struct bt_conn *conn);
|
||||||
|
|
||||||
|
/** @brief Reply if incoming pairing was confirmed by user.
|
||||||
|
*
|
||||||
|
* This function should be called only after pairing_confirm callback from
|
||||||
|
* bt_conn_auth_cb structure was called if user confirmed incoming pairing.
|
||||||
|
*
|
||||||
|
* @param conn Connection object.
|
||||||
|
*
|
||||||
|
* @return Zero on success or negative error code otherwise
|
||||||
|
*/
|
||||||
|
int bt_conn_auth_pairing_confirm(struct bt_conn *conn);
|
||||||
|
|
||||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||||
/** @brief Reply with entered PIN code.
|
/** @brief Reply with entered PIN code.
|
||||||
*
|
*
|
||||||
|
|
|
@ -434,9 +434,6 @@ void bt_conn_ssp_auth(struct bt_conn *conn, uint32_t passkey)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: As pairing acceptor call user pairing consent API callback. */
|
|
||||||
|
|
||||||
/* Start interactive authentication if valid, default to justworks. */
|
|
||||||
switch (conn->br.pairing_method) {
|
switch (conn->br.pairing_method) {
|
||||||
case PASSKEY_CONFIRM:
|
case PASSKEY_CONFIRM:
|
||||||
atomic_set_bit(conn->flags, BT_CONN_USER);
|
atomic_set_bit(conn->flags, BT_CONN_USER);
|
||||||
|
@ -450,9 +447,17 @@ void bt_conn_ssp_auth(struct bt_conn *conn, uint32_t passkey)
|
||||||
atomic_set_bit(conn->flags, BT_CONN_USER);
|
atomic_set_bit(conn->flags, BT_CONN_USER);
|
||||||
bt_auth->passkey_entry(conn);
|
bt_auth->passkey_entry(conn);
|
||||||
break;
|
break;
|
||||||
default:
|
case JUST_WORKS:
|
||||||
|
/* TODO do this only for incoming pairing */
|
||||||
|
if (bt_auth && bt_auth->pairing_confirm) {
|
||||||
|
atomic_set_bit(conn->flags, BT_CONN_USER);
|
||||||
|
bt_auth->pairing_confirm(conn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ssp_confirm_reply(conn);
|
ssp_confirm_reply(conn);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1528,6 +1533,26 @@ int bt_conn_auth_cancel(struct bt_conn *conn)
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bt_conn_auth_pairing_confirm(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
if (!bt_auth) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (conn->type) {
|
||||||
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
||||||
|
case BT_CONN_TYPE_LE:
|
||||||
|
return bt_smp_auth_pairing_confirm(conn);
|
||||||
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
||||||
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||||
|
case BT_CONN_TYPE_BR:
|
||||||
|
return ssp_confirm_reply(conn);
|
||||||
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */
|
#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */
|
||||||
|
|
||||||
static void background_scan_init(void)
|
static void background_scan_init(void)
|
||||||
|
|
|
@ -94,6 +94,7 @@ enum {
|
||||||
SMP_FLAG_USER, /* if waiting for user input */
|
SMP_FLAG_USER, /* if waiting for user input */
|
||||||
SMP_FLAG_BOND, /* if bonding */
|
SMP_FLAG_BOND, /* if bonding */
|
||||||
SMP_FLAG_SC_DEBUG_KEY, /* if Secure Connection are using debug key */
|
SMP_FLAG_SC_DEBUG_KEY, /* if Secure Connection are using debug key */
|
||||||
|
SMP_FLAG_SEC_REQ, /* if Security Request was sent/received */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SMP channel specific context */
|
/* SMP channel specific context */
|
||||||
|
@ -1112,13 +1113,22 @@ static uint8_t legacy_pairing_req(struct bt_smp *smp, uint8_t remote_io)
|
||||||
|
|
||||||
BT_DBG("");
|
BT_DBG("");
|
||||||
|
|
||||||
|
smp->method = legacy_get_pair_method(smp, remote_io);
|
||||||
|
|
||||||
|
/* ask for consent if pairing is not due to sending SecReq*/
|
||||||
|
if (smp->method == JUST_WORKS &&
|
||||||
|
!atomic_test_bit(&smp->flags, SMP_FLAG_SEC_REQ) &&
|
||||||
|
bt_auth && bt_auth->pairing_confirm) {
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_USER);
|
||||||
|
bt_auth->pairing_confirm(smp->chan.conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = send_pairing_rsp(smp);
|
ret = send_pairing_rsp(smp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
smp->method = legacy_get_pair_method(smp, remote_io);
|
|
||||||
|
|
||||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
|
||||||
|
|
||||||
return legacy_request_tk(smp);
|
return legacy_request_tk(smp);
|
||||||
|
@ -1310,6 +1320,15 @@ static uint8_t legacy_pairing_rsp(struct bt_smp *smp, uint8_t remote_io)
|
||||||
|
|
||||||
smp->method = legacy_get_pair_method(smp, remote_io);
|
smp->method = legacy_get_pair_method(smp, remote_io);
|
||||||
|
|
||||||
|
/* ask for consent if this is due to received SecReq */
|
||||||
|
if (smp->method == JUST_WORKS &&
|
||||||
|
atomic_test_bit(&smp->flags, SMP_FLAG_SEC_REQ) &&
|
||||||
|
bt_auth && bt_auth->pairing_confirm) {
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_USER);
|
||||||
|
bt_auth->pairing_confirm(smp->chan.conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = legacy_request_tk(smp);
|
ret = legacy_request_tk(smp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1482,7 +1501,6 @@ static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
|
||||||
if ((rsp->auth_req & BT_SMP_AUTH_SC) &&
|
if ((rsp->auth_req & BT_SMP_AUTH_SC) &&
|
||||||
(req->auth_req & BT_SMP_AUTH_SC)) {
|
(req->auth_req & BT_SMP_AUTH_SC)) {
|
||||||
atomic_set_bit(&smp->flags, SMP_FLAG_SC);
|
atomic_set_bit(&smp->flags, SMP_FLAG_SC);
|
||||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
|
|
||||||
|
|
||||||
rsp->init_key_dist &= RECV_KEYS_SC;
|
rsp->init_key_dist &= RECV_KEYS_SC;
|
||||||
rsp->resp_key_dist &= SEND_KEYS_SC;
|
rsp->resp_key_dist &= SEND_KEYS_SC;
|
||||||
|
@ -1514,6 +1532,21 @@ static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
|
||||||
}
|
}
|
||||||
#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
||||||
|
|
||||||
|
if (smp->method == JUST_WORKS) {
|
||||||
|
#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
||||||
|
return BT_SMP_ERR_AUTH_REQUIREMENTS;
|
||||||
|
#else
|
||||||
|
/* ask for consent if pairing is not due to sending SecReq*/
|
||||||
|
if (!atomic_test_bit(&smp->flags, SMP_FLAG_SEC_REQ) &&
|
||||||
|
bt_auth && bt_auth->pairing_confirm) {
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_USER);
|
||||||
|
bt_auth->pairing_confirm(smp->chan.conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
|
||||||
return send_pairing_rsp(smp);
|
return send_pairing_rsp(smp);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1649,15 +1682,23 @@ static uint8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf)
|
||||||
|
|
||||||
smp->method = get_pair_method(smp, rsp->io_capability);
|
smp->method = get_pair_method(smp, rsp->io_capability);
|
||||||
|
|
||||||
#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
|
||||||
if (smp->method == JUST_WORKS) {
|
|
||||||
return BT_SMP_ERR_AUTH_REQUIREMENTS;
|
|
||||||
}
|
|
||||||
#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
|
||||||
|
|
||||||
smp->local_dist &= SEND_KEYS_SC;
|
smp->local_dist &= SEND_KEYS_SC;
|
||||||
smp->remote_dist &= RECV_KEYS_SC;
|
smp->remote_dist &= RECV_KEYS_SC;
|
||||||
|
|
||||||
|
if (smp->method == JUST_WORKS) {
|
||||||
|
#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
||||||
|
return BT_SMP_ERR_AUTH_REQUIREMENTS;
|
||||||
|
#else
|
||||||
|
/* ask for consent if this is due to received SecReq */
|
||||||
|
if (atomic_test_bit(&smp->flags, SMP_FLAG_SEC_REQ) &&
|
||||||
|
bt_auth && bt_auth->pairing_confirm) {
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_USER);
|
||||||
|
bt_auth->pairing_confirm(smp->chan.conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
||||||
|
}
|
||||||
|
|
||||||
if (!sc_local_pkey_valid) {
|
if (!sc_local_pkey_valid) {
|
||||||
atomic_set_bit(&smp->flags, SMP_FLAG_PKEY_SEND);
|
atomic_set_bit(&smp->flags, SMP_FLAG_PKEY_SEND);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2278,6 +2319,8 @@ pair:
|
||||||
return BT_SMP_ERR_UNSPECIFIED;
|
return BT_SMP_ERR_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_SEC_REQ);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -3340,11 +3383,65 @@ int bt_smp_auth_cancel(struct bt_conn *conn)
|
||||||
case PASSKEY_CONFIRM:
|
case PASSKEY_CONFIRM:
|
||||||
return smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
|
return smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
|
||||||
case JUST_WORKS:
|
case JUST_WORKS:
|
||||||
|
return smp_error(smp, BT_SMP_ERR_UNSPECIFIED);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
||||||
|
int bt_smp_auth_pairing_confirm(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
struct bt_smp *smp;
|
||||||
|
|
||||||
|
smp = smp_chan_get(conn);
|
||||||
|
if (!smp) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!atomic_test_and_clear_bit(&smp->flags, SMP_FLAG_USER)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BLUETOOTH_CENTRAL)
|
||||||
|
if (conn->role == BT_CONN_ROLE_MASTER) {
|
||||||
|
if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) {
|
||||||
|
atomic_set_bit(&smp->allowed_cmds,
|
||||||
|
BT_SMP_CMD_PAIRING_CONFIRM);
|
||||||
|
return legacy_send_pairing_confirm(smp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sc_local_pkey_valid) {
|
||||||
|
atomic_set_bit(&smp->flags, SMP_FLAG_PKEY_SEND);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
|
||||||
|
return sc_send_public_key(smp);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLUETOOTH_CENTRAL */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BLUETOOTH_PERIPHERAL)
|
||||||
|
if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) {
|
||||||
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
|
||||||
|
return send_pairing_rsp(smp);
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
|
||||||
|
if (send_pairing_rsp(smp)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLUETOOTH_PERIPHERAL */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int bt_smp_auth_pairing_confirm(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
/* confirm_pairing will never be called in LE SC only mode */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
||||||
|
|
||||||
void bt_smp_update_keys(struct bt_conn *conn)
|
void bt_smp_update_keys(struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
struct bt_smp *smp;
|
struct bt_smp *smp;
|
||||||
|
|
|
@ -144,6 +144,7 @@ int bt_smp_init(void);
|
||||||
|
|
||||||
int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
|
int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
|
||||||
int bt_smp_auth_passkey_confirm(struct bt_conn *conn);
|
int bt_smp_auth_passkey_confirm(struct bt_conn *conn);
|
||||||
|
int bt_smp_auth_pairing_confirm(struct bt_conn *conn);
|
||||||
int bt_smp_auth_cancel(struct bt_conn *conn);
|
int bt_smp_auth_cancel(struct bt_conn *conn);
|
||||||
|
|
||||||
/** brief Verify signed message
|
/** brief Verify signed message
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue