From cc0d2447f11a9ab1c09c14f5a07fd54a4e72033d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Morales?= Date: Tue, 14 Jan 2020 13:32:51 +0100 Subject: [PATCH] Bluetooth: smp: Adding Legacy OOB pairing support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for Legacy pairing using OOB Temporary Key Signed-off-by: Iván Morales --- include/bluetooth/conn.h | 14 ++++++++ subsys/bluetooth/host/hci_core.c | 9 ++++- subsys/bluetooth/host/smp.c | 58 +++++++++++++++++++++++++++++--- subsys/bluetooth/host/smp.h | 1 + 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index 6fbbc36c29f..fca345c5319 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -618,6 +618,20 @@ void bt_set_bondable(bool enable); */ void bt_set_oob_data_flag(bool enable); +/** + * @brief Set OOB Temporary Key to be used for pairing + * + * This function allows to set OOB data for the LE legacy pairing procedure. The + * function should only be called in response to the oob_data_request() callback + * provided that the legacy method is user pairing. + * + * @param conn Connection object + * @param tk Pointer to 16 byte long TK array + * + * @return Zero on success or -EINVAL if NULL + */ +int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const u8_t *tk); + /** * @brief Set OOB data during LE SC pairing procedure * diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 703469b9a9e..1f1c81208df 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -6876,6 +6876,13 @@ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) } #if defined(CONFIG_BT_SMP) +#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) +int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const u8_t *tk) +{ + return bt_smp_le_oob_set_tk(conn, tk); +} +#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ + int bt_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local, const struct bt_le_oob_sc_data *oobd_remote) @@ -6897,4 +6904,4 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn, return bt_smp_le_oob_get_sc_data(conn, oobd_local, oobd_remote); } -#endif +#endif /* defined(CONFIG_BT_SMP) */ diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index fe15d63e21c..254db65bed2 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -95,6 +95,7 @@ enum pairing_method { PASSKEY_CONFIRM, /* Passkey confirm */ PASSKEY_ROLE, /* Passkey Entry depends on role */ LE_SC_OOB, /* LESC Out of Band */ + LEGACY_OOB, /* Legacy Out of Band */ }; enum { @@ -2194,6 +2195,11 @@ static u8_t legacy_get_pair_method(struct bt_smp *smp, u8_t remote_io) req = (struct bt_smp_pairing *)&smp->preq[1]; rsp = (struct bt_smp_pairing *)&smp->prsp[1]; + /* if both sides have OOB data use OOB */ + if ((req->oob_flag & rsp->oob_flag) & BT_SMP_OOB_DATA_MASK) { + return LEGACY_OOB; + } + /* if none side requires MITM use JustWorks */ if (!((req->auth_req | rsp->auth_req) & BT_SMP_AUTH_MITM)) { return JUST_WORKS; @@ -2234,6 +2240,19 @@ static u8_t legacy_request_tk(struct bt_smp *smp) } switch (smp->method) { + case LEGACY_OOB: + if (bt_auth && bt_auth->oob_data_request) { + struct bt_conn_oob_info info = { + .type = BT_CONN_OOB_LE_LEGACY, + }; + + atomic_set_bit(smp->flags, SMP_FLAG_USER); + bt_auth->oob_data_request(smp->chan.chan.conn, &info); + } else { + return BT_SMP_ERR_OOB_NOT_AVAIL; + } + + break; case PASSKEY_DISPLAY: if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_INVALID) { @@ -2420,11 +2439,8 @@ static u8_t legacy_pairing_confirm(struct bt_smp *smp) return 0; } -static void legacy_passkey_entry(struct bt_smp *smp, unsigned int passkey) +static void legacy_user_tk_entry(struct bt_smp *smp) { - passkey = sys_cpu_to_le32(passkey); - memcpy(smp->tk, &passkey, sizeof(passkey)); - if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_CFM_DELAYED)) { return; } @@ -2446,6 +2462,14 @@ static void legacy_passkey_entry(struct bt_smp *smp, unsigned int passkey) } } +static void legacy_passkey_entry(struct bt_smp *smp, unsigned int passkey) +{ + passkey = sys_cpu_to_le32(passkey); + memcpy(smp->tk, &passkey, sizeof(passkey)); + + legacy_user_tk_entry(smp); +} + static u8_t smp_encrypt_info(struct bt_smp *smp, struct net_buf *buf) { BT_DBG(""); @@ -5016,6 +5040,30 @@ int bt_smp_auth_passkey_confirm(struct bt_conn *conn) return 0; } +#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) +int bt_smp_le_oob_set_tk(struct bt_conn *conn, const u8_t *tk) +{ + struct bt_smp *smp; + + smp = smp_chan_get(conn); + if (!smp || !tk) { + return -EINVAL; + } + + BT_DBG("%s", bt_hex(tk, 16)); + + if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) { + return -EINVAL; + } + + memcpy(smp->tk, tk, 16*sizeof(u8_t)); + + legacy_user_tk_entry(smp); + + return 0; +} +#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ + int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob) { int err; @@ -5174,6 +5222,7 @@ int bt_smp_auth_cancel(struct bt_conn *conn) case PASSKEY_CONFIRM: return smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED); case LE_SC_OOB: + case LEGACY_OOB: return smp_error(smp, BT_SMP_ERR_OOB_NOT_AVAIL); case JUST_WORKS: return smp_error(smp, BT_SMP_ERR_UNSPECIFIED); @@ -5349,6 +5398,7 @@ void bt_smp_update_keys(struct bt_conn *conn) case PASSKEY_INPUT: case PASSKEY_CONFIRM: case LE_SC_OOB: + case LEGACY_OOB: conn->le.keys->flags |= BT_KEYS_AUTHENTICATED; break; case JUST_WORKS: diff --git a/subsys/bluetooth/host/smp.h b/subsys/bluetooth/host/smp.h index 0e02e115c64..a4aeff3d425 100644 --- a/subsys/bluetooth/host/smp.h +++ b/subsys/bluetooth/host/smp.h @@ -138,6 +138,7 @@ 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_le_oob_set_tk(struct bt_conn *conn, const u8_t *tk); int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob); int bt_smp_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local,