diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 5b83a91da65..f7e642bea9a 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1030,28 +1030,11 @@ static int start_security(struct bt_conn *conn) } #endif /* CONFIG_BT_BREDR */ - switch (conn->role) { -#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_SMP) - case BT_HCI_ROLE_MASTER: - { - if (!bt_smp_keys_check(conn)) { - return bt_smp_send_pairing_req(conn); - } - /* LE SC LTK and legacy master LTK are stored in same place */ - return bt_conn_le_start_encryption(conn, - conn->le.keys->ltk.rand, - conn->le.keys->ltk.ediv, - conn->le.keys->ltk.val, - conn->le.keys->enc_size); - } -#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_SMP */ -#if defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_SMP) - case BT_HCI_ROLE_SLAVE: - return bt_smp_send_security_req(conn); -#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_SMP */ - default: - return -EINVAL; + if (IS_ENABLED(CONFIG_BT_SMP)) { + return bt_smp_start_security(conn); } + + return -EINVAL; } int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 2804ed8e2cc..0ca60fac68e 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3211,18 +3211,36 @@ static void le_ltk_neg_reply(u16_t handle) } cp = net_buf_add(buf, sizeof(*cp)); - cp->handle = handle; + cp->handle = sys_cpu_to_le16(handle); bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, buf); } +static void le_ltk_reply(u16_t handle, u8_t *ltk) +{ + struct bt_hci_cp_le_ltk_req_reply *cp; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, + sizeof(*cp)); + if (!buf) { + BT_ERR("Out of command buffers"); + return; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle = sys_cpu_to_le16(handle); + memcpy(cp->ltk, ltk, sizeof(cp->ltk)); + + bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); +} + static void le_ltk_request(struct net_buf *buf) { struct bt_hci_evt_le_ltk_request *evt = (void *)buf->data; - struct bt_hci_cp_le_ltk_req_reply *cp; struct bt_conn *conn; u16_t handle; - u8_t tk[16]; + u8_t ltk[16]; handle = sys_le16_to_cpu(evt->handle); @@ -3234,92 +3252,12 @@ static void le_ltk_request(struct net_buf *buf) return; } - /* - * if TK is present use it, that means pairing is in progress and - * we should use new TK for encryption - * - * Both legacy STK and LE SC LTK have rand and ediv equal to zero. - */ - if (evt->rand == 0U && evt->ediv == 0U && bt_smp_get_tk(conn, tk)) { - buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, - sizeof(*cp)); - if (!buf) { - BT_ERR("Out of command buffers"); - goto done; - } - - cp = net_buf_add(buf, sizeof(*cp)); - cp->handle = evt->handle; - memcpy(cp->ltk, tk, sizeof(cp->ltk)); - - bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); - goto done; + if (bt_smp_request_ltk(conn, evt->rand, evt->ediv, ltk)) { + le_ltk_reply(handle, ltk); + } else { + le_ltk_neg_reply(handle); } - if (!conn->le.keys) { - conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, conn->id, - &conn->le.dst); - if (!conn->le.keys) { - conn->le.keys = bt_keys_find(BT_KEYS_SLAVE_LTK, - conn->id, &conn->le.dst); - } - } - - if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_LTK_P256) && - evt->rand == 0U && evt->ediv == 0U) { - buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, - sizeof(*cp)); - if (!buf) { - BT_ERR("Out of command buffers"); - goto done; - } - - cp = net_buf_add(buf, sizeof(*cp)); - cp->handle = evt->handle; - - /* use only enc_size bytes of key for encryption */ - memcpy(cp->ltk, conn->le.keys->ltk.val, - conn->le.keys->enc_size); - if (conn->le.keys->enc_size < sizeof(cp->ltk)) { - (void)memset(cp->ltk + conn->le.keys->enc_size, 0, - sizeof(cp->ltk) - conn->le.keys->enc_size); - } - - bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); - goto done; - } - -#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) - if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) && - !memcmp(conn->le.keys->slave_ltk.rand, &evt->rand, 8) && - !memcmp(conn->le.keys->slave_ltk.ediv, &evt->ediv, 2)) { - buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, - sizeof(*cp)); - if (!buf) { - BT_ERR("Out of command buffers"); - goto done; - } - - cp = net_buf_add(buf, sizeof(*cp)); - cp->handle = evt->handle; - - /* use only enc_size bytes of key for encryption */ - memcpy(cp->ltk, conn->le.keys->slave_ltk.val, - conn->le.keys->enc_size); - if (conn->le.keys->enc_size < sizeof(cp->ltk)) { - (void)memset(cp->ltk + conn->le.keys->enc_size, 0, - sizeof(cp->ltk) - conn->le.keys->enc_size); - } - - bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); - goto done; - } -#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */ - - le_ltk_neg_reply(evt->handle); - bt_smp_keys_reject(conn); - -done: bt_conn_unref(conn); } #endif /* CONFIG_BT_SMP */ diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 24f0544dc83..9d34daa4f55 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -308,7 +308,7 @@ no_callbacks: static u8_t legacy_get_pair_method(struct bt_smp *smp, u8_t remote_io); #endif -bool bt_smp_keys_check(struct bt_conn *conn) +static bool smp_keys_check(struct bt_conn *conn) { if (atomic_test_bit(conn->flags, BT_CONN_FORCE_PAIR)) { return false; @@ -2556,8 +2556,91 @@ static struct bt_smp *smp_chan_get(struct bt_conn *conn) return CONTAINER_OF(chan, struct bt_smp, chan); } +bool bt_smp_request_ltk(struct bt_conn *conn, u64_t rand, u16_t ediv, u8_t *ltk) +{ + struct bt_smp *smp; + u8_t enc_size; + + smp = smp_chan_get(conn); + if (!smp) { + return false; + } + + /* + * Both legacy STK and LE SC LTK have rand and ediv equal to zero. + * If pairing is in progress use the TK for encryption. + */ + if (ediv == 0U && rand == 0U && + atomic_test_bit(smp->flags, SMP_FLAG_PAIRING) && + atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) { + enc_size = get_encryption_key_size(smp); + + /* + * We keep both legacy STK and LE SC LTK in TK. + * Also use only enc_size bytes of key for encryption. + */ + memcpy(ltk, smp->tk, enc_size); + if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) { + (void)memset(ltk + enc_size, 0, + BT_SMP_MAX_ENC_KEY_SIZE - enc_size); + } + + return true; + } + + if (!conn->le.keys) { + conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, conn->id, + &conn->le.dst); + if (!conn->le.keys) { + conn->le.keys = bt_keys_find(BT_KEYS_SLAVE_LTK, + conn->id, &conn->le.dst); + } + } + + if (ediv == 0U && rand == 0U && + conn->le.keys && (conn->le.keys->keys & BT_KEYS_LTK_P256)) { + enc_size = conn->le.keys->enc_size; + + memcpy(ltk, conn->le.keys->ltk.val, enc_size); + if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) { + (void)memset(ltk + enc_size, 0, + BT_SMP_MAX_ENC_KEY_SIZE - enc_size); + } + + return true; + } + +#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) + if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) && + !memcmp(conn->le.keys->slave_ltk.rand, &rand, 8) && + !memcmp(conn->le.keys->slave_ltk.ediv, &ediv, 2)) { + enc_size = conn->le.keys->enc_size; + + memcpy(ltk, conn->le.keys->slave_ltk.val, enc_size); + if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) { + (void)memset(ltk + enc_size, 0, + BT_SMP_MAX_ENC_KEY_SIZE - enc_size); + } + + return true; + } +#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */ + + if (atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) { + /* Notify higher level that security failed if security was + * initiated by slave. + */ + bt_conn_security_changed(smp->chan.chan.conn, + BT_SECURITY_ERR_PIN_OR_KEY_MISSING); + + } + + smp_reset(smp); + return false; +} + #if defined(CONFIG_BT_PERIPHERAL) -int bt_smp_send_security_req(struct bt_conn *conn) +static int smp_send_security_req(struct bt_conn *conn) { struct bt_smp *smp; struct bt_smp_security_request *req; @@ -2580,7 +2663,7 @@ int bt_smp_send_security_req(struct bt_conn *conn) } /* early verify if required sec level if reachable */ - if (!(sec_level_reachable(conn) || bt_smp_keys_check(conn))) { + if (!(sec_level_reachable(conn) || smp_keys_check(conn))) { return -EINVAL; } @@ -2752,7 +2835,7 @@ static u8_t sc_send_public_key(struct bt_smp *smp) } #if defined(CONFIG_BT_CENTRAL) -int bt_smp_send_pairing_req(struct bt_conn *conn) +static int smp_send_pairing_req(struct bt_conn *conn) { struct bt_smp *smp; struct bt_smp_pairing *req; @@ -3623,7 +3706,7 @@ static u8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf) return 0; pair: - if (bt_smp_send_pairing_req(conn) < 0) { + if (smp_send_pairing_req(conn) < 0) { return BT_SMP_ERR_UNSPECIFIED; } @@ -4985,6 +5068,33 @@ int bt_passkey_set(unsigned int passkey) } #endif /* CONFIG_BT_FIXED_PASSKEY */ +int bt_smp_start_security(struct bt_conn *conn) +{ + switch (conn->role) { +#if defined(CONFIG_BT_CENTRAL) + case BT_HCI_ROLE_MASTER: + { + if (!smp_keys_check(conn)) { + return smp_send_pairing_req(conn); + } + + /* LE SC LTK and legacy master LTK are stored in same place */ + return bt_conn_le_start_encryption(conn, + conn->le.keys->ltk.rand, + conn->le.keys->ltk.ediv, + conn->le.keys->ltk.val, + conn->le.keys->enc_size); + } +#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_SMP */ +#if defined(CONFIG_BT_PERIPHERAL) + case BT_HCI_ROLE_SLAVE: + return smp_send_security_req(conn); +#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_SMP */ + default: + return -EINVAL; + } +} + void bt_smp_update_keys(struct bt_conn *conn) { struct bt_smp *smp; @@ -5062,55 +5172,6 @@ void bt_smp_update_keys(struct bt_conn *conn) } } -bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk) -{ - struct bt_smp *smp; - u8_t enc_size; - - smp = smp_chan_get(conn); - if (!smp) { - return false; - } - - if (!atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) { - return false; - } - - if (!atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) { - return false; - } - - enc_size = get_encryption_key_size(smp); - - /* - * We keep both legacy STK and LE SC LTK in TK. - * Also use only enc_size bytes of key for encryption. - */ - memcpy(tk, smp->tk, enc_size); - if (enc_size < sizeof(smp->tk)) { - (void)memset(tk + enc_size, 0, sizeof(smp->tk) - enc_size); - } - - return true; -} - -void bt_smp_keys_reject(struct bt_conn *conn) -{ - struct bt_smp *smp; - - smp = smp_chan_get(conn); - if (!smp) { - return; - } - - if (atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) { - bt_conn_security_changed(smp->chan.chan.conn, - BT_SECURITY_ERR_PIN_OR_KEY_MISSING); - } - - smp_reset(smp); -} - static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) { int i; diff --git a/subsys/bluetooth/host/smp.h b/subsys/bluetooth/host/smp.h index 9620b8013f6..73b6ea0c33a 100644 --- a/subsys/bluetooth/host/smp.h +++ b/subsys/bluetooth/host/smp.h @@ -123,12 +123,11 @@ struct bt_smp_dhkey_check { u8_t e[16]; } __packed; -int bt_smp_send_pairing_req(struct bt_conn *conn); -int bt_smp_send_security_req(struct bt_conn *conn); +int bt_smp_start_security(struct bt_conn *conn); +bool bt_smp_request_ltk(struct bt_conn *conn, u64_t rand, u16_t ediv, + u8_t *ltk); + void bt_smp_update_keys(struct bt_conn *conn); -bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk); -bool bt_smp_keys_check(struct bt_conn *conn); -void bt_smp_keys_reject(struct bt_conn *conn); int bt_smp_br_send_pairing_req(struct bt_conn *conn);