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_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.

View file

@ -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;

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);
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) */

View file

@ -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();
}