Bluetooth: smp: Adding Legacy OOB only mode and no JW/Passkey mode

Added CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY option that completely disables
all legacy and SC pairing modes(except for Out of Band) and frees the
memory previously used by these.

Added CONFIG_BT_SMP_DISABLE_LEGACY_JW_PASSKEY option that force rejects
pair requests that lead to legacy Just Works or Passkey pairing.

Signed-off-by: Iván Morales <ivan98ams@gmail.com>
This commit is contained in:
Iván Morales 2020-01-14 16:00:01 +01:00 committed by Johan Hedberg
commit e85dd8af5d
4 changed files with 75 additions and 8 deletions

View file

@ -293,7 +293,6 @@ config BT_SMP
select TINYCRYPT_AES select TINYCRYPT_AES
select TINYCRYPT_AES_CMAC select TINYCRYPT_AES_CMAC
select BT_RPA select BT_RPA
select BT_ECC
help help
This option enables support for the Security Manager Protocol This option enables support for the Security Manager Protocol
(SMP), making it possible to pair devices over LE. (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 Security Mode 1 Level 4 stands for authenticated LE Secure Connections
pairing with encryption. Enabling this option disables legacy pairing. 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 config BT_SMP_ALLOW_UNAUTH_OVERWRITE
bool "Allow unauthenticated pairing for paired device" bool "Allow unauthenticated pairing for paired device"
help help
@ -545,6 +558,7 @@ endif # BT_HCI_HOST
config BT_ECC config BT_ECC
bool "Enable ECDH key generation support" bool "Enable ECDH key generation support"
default y if !BT_SMP_OOB_LEGACY_PAIR_ONLY
help help
This option adds support for ECDH HCI commands. This option adds support for ECDH HCI commands.

View file

@ -1123,6 +1123,11 @@ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) &&
sec > BT_SECURITY_L3) {
return -EOPNOTSUPP;
}
/* nothing to do */ /* nothing to do */
if (conn->sec_level >= sec || conn->required_sec_level >= sec) { if (conn->sec_level >= sec || conn->required_sec_level >= sec) {
return 0; return 0;

View file

@ -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); err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data);
if (err) { if (err) {
return 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) */ #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, 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_local,
const struct bt_le_oob_sc_data *oobd_remote) 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); 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) */ #endif /* defined(CONFIG_BT_SMP) */

View file

@ -80,13 +80,25 @@
#endif /* CONFIG_BT_BONDABLE */ #endif /* CONFIG_BT_BONDABLE */
#if defined(CONFIG_BT_BREDR) #if defined(CONFIG_BT_BREDR)
#define BT_SMP_AUTH_MASK_SC 0x2f #define BT_SMP_AUTH_MASK_SC 0x2f
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC |\ #if defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
BT_SMP_AUTH_CT2) #define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_CT2)
#else #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 #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) #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 { enum pairing_method {
JUST_WORKS, /* JustWorks pairing */ 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 */ #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 */ /* 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 */] = { static const u8_t gen_method_sc[5 /* remote */][5 /* local */] = {
{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT }, { 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_DISPLAY, PASSKEY_CONFIRM, PASSKEY_INPUT, JUST_WORKS,
PASSKEY_CONFIRM }, PASSKEY_CONFIRM },
}; };
#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
static const u8_t sc_debug_public_key[64] = { static const u8_t sc_debug_public_key[64] = {
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac, 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) 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 !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) { if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
return legacy_get_pair_method(smp, remote_io); return legacy_get_pair_method(smp, remote_io);
} }
#endif #endif
#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
struct bt_smp_pairing *req, *rsp;
req = (struct bt_smp_pairing *)&smp->preq[1]; req = (struct bt_smp_pairing *)&smp->preq[1];
rsp = (struct bt_smp_pairing *)&smp->prsp[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()]; 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) 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); 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 || if (!conn->le.keys ||
!(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) { !(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
return true; 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); 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(); sc_public_key = bt_pub_key_get();
#endif
return 0; 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) 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)) { if (bt_dh_key_gen(smp->pkey, bt_smp_dhkey_ready)) {
return BT_SMP_ERR_UNSPECIFIED; 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) */ #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 bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob)
{ {
int err; 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; 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, static bool le_sc_oob_data_check(struct bt_smp *smp, bool oobd_local_present,
bool oobd_remote_present) bool oobd_remote_present)
{ {
@ -5201,6 +5239,7 @@ int bt_smp_le_oob_get_sc_data(struct bt_conn *conn,
return 0; return 0;
} }
#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
int bt_smp_auth_cancel(struct bt_conn *conn) 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. * "LE Read Local P-256 Public Key" and "LE Generate DH Key" commands.
* Otherwise LE SC are not supported. * 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) && return BT_CMD_TEST(bt_dev.supported_commands, 34, 1) &&
BT_CMD_TEST(bt_dev.supported_commands, 34, 2); 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_DBG("LE SC %s", sc_supported ? "enabled" : "disabled");
if (!IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
bt_pub_key_gen(&pub_key_cb); bt_pub_key_gen(&pub_key_cb);
}
return smp_self_test(); return smp_self_test();
} }