Bluetooth: Host: Add error to security changed callback
Add security error to security_changed callback. Call this callback when security has failed and provide current security level and error. Reason for failure can be. - Pairing procedure failed, pairing aborted before link encryption. - Link encrypt procedure failed - Link key refresh procedure failed. Fix missing bt_conn_unref on encryption key refresh with error status. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
f1c7371494
commit
6d4b842a10
8 changed files with 59 additions and 32 deletions
|
@ -442,8 +442,10 @@ struct bt_conn_cb {
|
||||||
*
|
*
|
||||||
* @param conn Connection object.
|
* @param conn Connection object.
|
||||||
* @param level New security level of the connection.
|
* @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) */
|
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
|
||||||
struct bt_conn_cb *_next;
|
struct bt_conn_cb *_next;
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,13 +58,18 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
|
||||||
printk("Disconnected from %s (reason 0x%02x)\n", addr, 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];
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
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 = {
|
static struct bt_conn_cb conn_callbacks = {
|
||||||
|
|
|
@ -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);
|
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];
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
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 = {
|
static struct bt_conn_cb conn_callbacks = {
|
||||||
|
|
|
@ -984,13 +984,13 @@ u8_t bt_conn_enc_key_size(struct bt_conn *conn)
|
||||||
return 0;
|
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;
|
struct bt_conn_cb *cb;
|
||||||
|
|
||||||
for (cb = callback_list; cb; cb = cb->_next) {
|
for (cb = callback_list; cb; cb = cb->_next) {
|
||||||
if (cb->security_changed) {
|
if (cb->security_changed) {
|
||||||
cb->security_changed(conn, conn->sec_level);
|
cb->security_changed(conn, conn->sec_level, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ void bt_conn_identity_resolved(struct bt_conn *conn);
|
||||||
|
|
||||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||||
/* Notify higher layers that connection security changed */
|
/* 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 */
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||||
|
|
||||||
/* Prepare a PDU to be sent over a connection */
|
/* Prepare a PDU to be sent over a connection */
|
||||||
|
|
|
@ -1699,19 +1699,23 @@ static enum bt_security_err security_err_get(u8_t hci_err)
|
||||||
return BT_SECURITY_ERR_UNSPECIFIED;
|
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)
|
static void reset_pairing(struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
|
#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);
|
||||||
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
||||||
atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE);
|
atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_BREDR */
|
||||||
|
|
||||||
/* Reset required security level to current operational */
|
/* Reset required security level to current operational */
|
||||||
conn->required_sec_level = conn->sec_level;
|
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)
|
static int reject_conn(const bt_addr_t *bdaddr, u8_t reason)
|
||||||
{
|
{
|
||||||
struct bt_hci_cp_reject_conn_req *cp;
|
struct bt_hci_cp_reject_conn_req *cp;
|
||||||
|
@ -3026,16 +3030,9 @@ static void hci_encrypt_change(struct net_buf *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt->status) {
|
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);
|
reset_pairing(conn);
|
||||||
#endif /* CONFIG_BT_BREDR */
|
bt_l2cap_encrypt_change(conn, evt->status);
|
||||||
}
|
bt_conn_security_changed(conn, security_err_get(evt->status));
|
||||||
bt_conn_unref(conn);
|
bt_conn_unref(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3072,13 +3069,12 @@ static void hci_encrypt_change(struct net_buf *buf)
|
||||||
bt_smp_br_send_pairing_req(conn);
|
bt_smp_br_send_pairing_req(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_pairing(conn);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_BREDR */
|
#endif /* CONFIG_BT_BREDR */
|
||||||
|
reset_pairing(conn);
|
||||||
|
|
||||||
bt_l2cap_encrypt_change(conn, evt->status);
|
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);
|
bt_conn_unref(conn);
|
||||||
}
|
}
|
||||||
|
@ -3100,7 +3096,10 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt->status) {
|
if (evt->status) {
|
||||||
|
reset_pairing(conn);
|
||||||
bt_l2cap_encrypt_change(conn, evt->status);
|
bt_l2cap_encrypt_change(conn, evt->status);
|
||||||
|
bt_conn_security_changed(conn, security_err_get(evt->status));
|
||||||
|
bt_conn_unref(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3122,8 +3121,9 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_BREDR */
|
#endif /* CONFIG_BT_BREDR */
|
||||||
|
|
||||||
|
reset_pairing(conn);
|
||||||
bt_l2cap_encrypt_change(conn, evt->status);
|
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);
|
bt_conn_unref(conn);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||||
|
|
|
@ -1584,9 +1584,16 @@ static void smp_pairing_complete(struct bt_smp *smp, u8_t status)
|
||||||
bt_auth->pairing_complete(smp->chan.chan.conn,
|
bt_auth->pairing_complete(smp->chan.chan.conn,
|
||||||
bond_flag);
|
bond_flag);
|
||||||
}
|
}
|
||||||
} else if (bt_auth && bt_auth->pairing_failed) {
|
} else {
|
||||||
bt_auth->pairing_failed(smp->chan.chan.conn,
|
u8_t auth_err = auth_err_get(status);
|
||||||
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);
|
smp_reset(smp);
|
||||||
|
|
|
@ -213,12 +213,20 @@ static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
#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];
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
conn_addr_str(conn, addr, sizeof(addr));
|
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
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue