diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index b3a2eb6d85c..f11d66424d2 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -293,7 +293,6 @@ config BT_SMP select TINYCRYPT_AES select TINYCRYPT_AES_CMAC select BT_RPA - select BT_ECC help This option enables support for the Security Manager Protocol (SMP), making it possible to pair devices over LE. @@ -349,6 +348,20 @@ config BT_SMP_SC_ONLY Security Mode 1 Level 4 stands for authenticated LE Secure Connections pairing with encryption. Enabling this option disables legacy pairing. +config BT_SMP_OOB_LEGACY_PAIR_ONLY + bool "Force Out Of Band Legacy pairing" + depends on !(BT_SMP_SC_PAIR_ONLY || BT_SMP_SC_ONLY) + help + This option disables Legacy and LE SC pairing and forces legacy OOB. + +config BT_SMP_DISABLE_LEGACY_JW_PASSKEY + bool "Forbid usage of insecure legacy pairing methods" + depends on !(BT_SMP_SC_PAIR_ONLY || BT_SMP_SC_ONLY || \ + BT_SMP_OOB_LEGACY_PAIR_ONLY) + help + This option disables Just Works and Passkey legacy pairing methods to + increase security. + config BT_SMP_ALLOW_UNAUTH_OVERWRITE bool "Allow unauthenticated pairing for paired device" help @@ -545,6 +558,7 @@ endif # BT_HCI_HOST config BT_ECC bool "Enable ECDH key generation support" + default y if !BT_SMP_OOB_LEGACY_PAIR_ONLY help This option adds support for ECDH HCI commands. diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index db221bb8058..8eefd058ba2 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1123,6 +1123,11 @@ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) return -EOPNOTSUPP; } + if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) && + sec > BT_SECURITY_L3) { + return -EOPNOTSUPP; + } + /* nothing to do */ if (conn->sec_level >= sec || conn->required_sec_level >= sec) { return 0; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 1f1c81208df..c1b21f2fbce 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -6865,7 +6865,8 @@ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) } - if (IS_ENABLED(CONFIG_BT_SMP)) { + if (IS_ENABLED(CONFIG_BT_SMP) && + !IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) { err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); if (err) { return err; @@ -6883,6 +6884,7 @@ int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const u8_t *tk) } #endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_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) @@ -6904,4 +6906,5 @@ 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 /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */ #endif /* defined(CONFIG_BT_SMP) */ diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 254db65bed2..130c68e0b1e 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -80,13 +80,25 @@ #endif /* CONFIG_BT_BONDABLE */ #if defined(CONFIG_BT_BREDR) + #define BT_SMP_AUTH_MASK_SC 0x2f -#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC |\ - BT_SMP_AUTH_CT2) +#if defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) +#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_CT2) #else +#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_CT2 |\ + BT_SMP_AUTH_SC) +#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */ + +#else + #define BT_SMP_AUTH_MASK_SC 0x0f +#if defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) +#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS) +#else #define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC) -#endif +#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */ + +#endif /* CONFIG_BT_BREDR */ enum pairing_method { JUST_WORKS, /* JustWorks pairing */ @@ -209,6 +221,7 @@ static const u8_t gen_method_legacy[5 /* remote */][5 /* local */] = { }; #endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */ +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) /* based on table 2.8 Core Spec 2.3.5.1 Vol. 3 Part H */ static const u8_t gen_method_sc[5 /* remote */][5 /* local */] = { { JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT }, @@ -220,6 +233,7 @@ static const u8_t gen_method_sc[5 /* remote */][5 /* local */] = { { PASSKEY_DISPLAY, PASSKEY_CONFIRM, PASSKEY_INPUT, JUST_WORKS, PASSKEY_CONFIRM }, }; +#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */ static const u8_t sc_debug_public_key[64] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac, @@ -347,14 +361,15 @@ static bool smp_keys_check(struct bt_conn *conn) static u8_t get_pair_method(struct bt_smp *smp, u8_t remote_io) { - struct bt_smp_pairing *req, *rsp; - #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) { return legacy_get_pair_method(smp, remote_io); } #endif +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) + struct bt_smp_pairing *req, *rsp; + req = (struct bt_smp_pairing *)&smp->preq[1]; rsp = (struct bt_smp_pairing *)&smp->prsp[1]; @@ -375,6 +390,9 @@ static u8_t get_pair_method(struct bt_smp *smp, u8_t remote_io) } return gen_method_sc[remote_io][get_io_capa()]; +#else + return JUST_WORKS; +#endif } static enum bt_security_err auth_err_get(u8_t smp_err) @@ -712,6 +730,17 @@ static bool update_keys_check(struct bt_smp *smp) conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst); } + if (IS_ENABLED(CONFIG_BT_SMP_DISABLE_LEGACY_JW_PASSKEY) && + !atomic_test_bit(smp->flags, SMP_FLAG_SC) && + smp->method != LEGACY_OOB) { + return false; + } + + if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) && + smp->method != LEGACY_OOB) { + return false; + } + if (!conn->le.keys || !(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) { return true; @@ -2598,7 +2627,9 @@ static int smp_init(struct bt_smp *smp) atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_FAIL); +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) sc_public_key = bt_pub_key_get(); +#endif return 0; } @@ -3902,6 +3933,10 @@ static u8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf) static u8_t generate_dhkey(struct bt_smp *smp) { + if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) { + return BT_SMP_ERR_UNSPECIFIED; + } + if (bt_dh_key_gen(smp->pkey, bt_smp_dhkey_ready)) { return BT_SMP_ERR_UNSPECIFIED; } @@ -5064,6 +5099,7 @@ int bt_smp_le_oob_set_tk(struct bt_conn *conn, const u8_t *tk) } #endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob) { int err; @@ -5097,7 +5133,9 @@ int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob) return 0; } +#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */ +#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) static bool le_sc_oob_data_check(struct bt_smp *smp, bool oobd_local_present, bool oobd_remote_present) { @@ -5201,6 +5239,7 @@ int bt_smp_le_oob_get_sc_data(struct bt_conn *conn, return 0; } +#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */ int bt_smp_auth_cancel(struct bt_conn *conn) { @@ -5470,6 +5509,10 @@ static bool le_sc_supported(void) * "LE Read Local P-256 Public Key" and "LE Generate DH Key" commands. * Otherwise LE SC are not supported. */ + if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) { + return false; + } + return BT_CMD_TEST(bt_dev.supported_commands, 34, 1) && BT_CMD_TEST(bt_dev.supported_commands, 34, 2); } @@ -5499,7 +5542,9 @@ int bt_smp_init(void) BT_DBG("LE SC %s", sc_supported ? "enabled" : "disabled"); - bt_pub_key_gen(&pub_key_cb); + if (!IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) { + bt_pub_key_gen(&pub_key_cb); + } return smp_self_test(); }