diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index 1ab90c3a0f3..d2585d33d19 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -442,8 +442,10 @@ struct bt_conn_cb { * * @param conn Connection object. * @param level New security level of the connection. + * @param err Security error. Zero for success, non-zero otherwise. */ - void (*security_changed)(struct bt_conn *conn, bt_security_t level); + void (*security_changed)(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err); #endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */ struct bt_conn_cb *_next; }; diff --git a/samples/bluetooth/peripheral_hids/src/main.c b/samples/bluetooth/peripheral_hids/src/main.c index 2addbef8291..50c0d25da7f 100644 --- a/samples/bluetooth/peripheral_hids/src/main.c +++ b/samples/bluetooth/peripheral_hids/src/main.c @@ -58,13 +58,18 @@ static void disconnected(struct bt_conn *conn, u8_t reason) printk("Disconnected from %s (reason 0x%02x)\n", addr, reason); } -static void security_changed(struct bt_conn *conn, bt_security_t level) +static void security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - printk("Security changed: %s level %u\n", addr, level); + if (!err) { + printk("Security changed: %s level %u", addr, level); + } else { + printk("Security failed: %s level %u err %d", addr, level, err); + } } static struct bt_conn_cb conn_callbacks = { diff --git a/samples/bluetooth/peripheral_sc_only/src/main.c b/samples/bluetooth/peripheral_sc_only/src/main.c index aaaa65637d6..b8329e21e0d 100644 --- a/samples/bluetooth/peripheral_sc_only/src/main.c +++ b/samples/bluetooth/peripheral_sc_only/src/main.c @@ -63,13 +63,18 @@ static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa, printk("Identity resolved %s -> %s\n", addr_rpa, addr_identity); } -static void security_changed(struct bt_conn *conn, bt_security_t level) +static void security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - printk("Security changed: %s level %u\n", addr, level); + if (!err) { + printk("Security changed: %s level %u", addr, level); + } else { + printk("Security failed: %s level %u err %d", addr, level, err); + } } static struct bt_conn_cb conn_callbacks = { diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 7208e18863c..9f60ef296c9 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -984,13 +984,13 @@ u8_t bt_conn_enc_key_size(struct bt_conn *conn) return 0; } -void bt_conn_security_changed(struct bt_conn *conn) +void bt_conn_security_changed(struct bt_conn *conn, enum bt_security_err err) { struct bt_conn_cb *cb; for (cb = callback_list; cb; cb = cb->_next) { if (cb->security_changed) { - cb->security_changed(conn, conn->sec_level); + cb->security_changed(conn, conn->sec_level, err); } } } diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 1090cf5ece6..30911e343a0 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -218,7 +218,7 @@ void bt_conn_identity_resolved(struct bt_conn *conn); #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) /* Notify higher layers that connection security changed */ -void bt_conn_security_changed(struct bt_conn *conn); +void bt_conn_security_changed(struct bt_conn *conn, enum bt_security_err err); #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ /* Prepare a PDU to be sent over a connection */ diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 17174df93d3..2c103225cb6 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -1699,19 +1699,23 @@ static enum bt_security_err security_err_get(u8_t hci_err) return BT_SECURITY_ERR_UNSPECIFIED; } } -#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */ -#if defined(CONFIG_BT_BREDR) static void reset_pairing(struct bt_conn *conn) { - atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING); - atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR); - atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE); +#if defined(CONFIG_BT_BREDR) + if (conn->type == BT_CONN_TYPE_BR) { + atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING); + atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR); + atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE); + } +#endif /* CONFIG_BT_BREDR */ /* Reset required security level to current operational */ conn->required_sec_level = conn->sec_level; } +#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */ +#if defined(CONFIG_BT_BREDR) static int reject_conn(const bt_addr_t *bdaddr, u8_t reason) { struct bt_hci_cp_reject_conn_req *cp; @@ -3026,16 +3030,9 @@ static void hci_encrypt_change(struct net_buf *buf) } if (evt->status) { - /* TODO report error */ - if (conn->type == BT_CONN_TYPE_LE) { - /* reset required security level in case of error */ - conn->required_sec_level = conn->sec_level; -#if defined(CONFIG_BT_BREDR) - } else { - bt_l2cap_encrypt_change(conn, evt->status); - reset_pairing(conn); -#endif /* CONFIG_BT_BREDR */ - } + reset_pairing(conn); + bt_l2cap_encrypt_change(conn, evt->status); + bt_conn_security_changed(conn, security_err_get(evt->status)); bt_conn_unref(conn); return; } @@ -3072,13 +3069,12 @@ static void hci_encrypt_change(struct net_buf *buf) bt_smp_br_send_pairing_req(conn); } } - - reset_pairing(conn); } #endif /* CONFIG_BT_BREDR */ + reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn); + bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } @@ -3100,7 +3096,10 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf) } if (evt->status) { + reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); + bt_conn_security_changed(conn, security_err_get(evt->status)); + bt_conn_unref(conn); return; } @@ -3122,8 +3121,9 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf) } #endif /* CONFIG_BT_BREDR */ + reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); - bt_conn_security_changed(conn); + bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index baee012e4f6..d83953fe5d1 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -1584,9 +1584,16 @@ static void smp_pairing_complete(struct bt_smp *smp, u8_t status) bt_auth->pairing_complete(smp->chan.chan.conn, bond_flag); } - } else if (bt_auth && bt_auth->pairing_failed) { - bt_auth->pairing_failed(smp->chan.chan.conn, - auth_err_get(status)); + } else { + u8_t auth_err = auth_err_get(status); + + if (!atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR)) { + bt_conn_security_changed(smp->chan.chan.conn, auth_err); + } + + if (bt_auth && bt_auth->pairing_failed) { + bt_auth->pairing_failed(smp->chan.chan.conn, auth_err); + } } smp_reset(smp); diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index e34e0301879..97c3b1d1bd8 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -213,12 +213,20 @@ static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa, #endif #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) -static void security_changed(struct bt_conn *conn, bt_security_t level) +static void security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) { char addr[BT_ADDR_LE_STR_LEN]; conn_addr_str(conn, addr, sizeof(addr)); - shell_print(ctx_shell, "Security changed: %s level %u", addr, level); + + if (!err) { + shell_print(ctx_shell, "Security changed: %s level %u", addr, + level); + } else { + shell_print(ctx_shell, "Security failed: %s level %u reason %d", + addr, level, err); + } } #endif