From f80deda9d2925ca934452a818310b9282e230502 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 8 Dec 2015 16:59:19 +0100 Subject: [PATCH] Bluetooth: SMP: Add support for Secure Connection Only Mode This patch introduce new Kconfig option that is used to indicate if device should operate in Secure Connection Only Mode. Enabling this option removes support for LE Legacy Pairing. Change-Id: If224b6786f4c840959fe87a31f0224bc1e21f90e Signed-off-by: Szymon Janc --- net/bluetooth/Kconfig | 10 +++++++ net/bluetooth/conn.c | 6 ++++ net/bluetooth/hci_core.c | 2 ++ net/bluetooth/keys.h | 2 ++ net/bluetooth/smp.c | 59 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 74 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index e694d37938e..ff458531518 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -129,6 +129,16 @@ config BLUETOOTH_SIGNING help This option enables data signing which is used for transferring authenticated data in an unencrypted connection. + +config BLUETOOTH_SMP_SC_ONLY + bool "Secure Connections Only Mode" + default n + help + This option enables support for Secure Connection Only Mode. In this + mode device shall only use Security Mode 1 Level 4 with exception + for services that only require Security Mode 1 Level 1 (no security). + Security Mode 1 Level 4 stands for authenticated LE Secure Connections + pairing with encryption. Enabling this option disables legacy pairing. endif # BLUETOOTH_SMP config BLUETOOTH_L2CAP_DYNAMIC_CHANNEL diff --git a/net/bluetooth/conn.c b/net/bluetooth/conn.c index 595bf3d087e..4582a007af5 100644 --- a/net/bluetooth/conn.c +++ b/net/bluetooth/conn.c @@ -213,6 +213,12 @@ int bt_conn_security(struct bt_conn *conn, bt_security_t sec) return -ENOTCONN; } +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (sec < BT_SECURITY_FIPS) { + return -EOPNOTSUPP; + } +#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */ + /* nothing to do */ if (conn->sec_level >= sec || conn->required_sec_level >= sec) { return 0; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 674945943c9..ea96dfef639 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -976,6 +976,7 @@ static void le_ltk_request(struct net_buf *buf) goto done; } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) if (conn->keys && (conn->keys->keys & BT_KEYS_SLAVE_LTK) && conn->keys->slave_ltk.rand == evt->rand && conn->keys->slave_ltk.ediv == evt->ediv) { @@ -1003,6 +1004,7 @@ static void le_ltk_request(struct net_buf *buf) bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); goto done; } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, sizeof(*cp)); if (!buf) { diff --git a/net/bluetooth/keys.h b/net/bluetooth/keys.h index 6ebd407e675..6d57a683f4d 100644 --- a/net/bluetooth/keys.h +++ b/net/bluetooth/keys.h @@ -57,7 +57,9 @@ struct bt_keys { uint8_t type; uint8_t enc_size; +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) struct bt_ltk slave_ltk; +#endif /* CONFIG_BLUETOOTH_SMP_SC_ONLY */ struct bt_ltk ltk; struct bt_irk irk; #if defined(CONFIG_BLUETOOTH_SIGNING) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 7155a8d8670..9c4cb666db9 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -849,7 +849,7 @@ static uint8_t get_encryption_key_size(struct bt_smp *smp) return min(req->max_key_size, rsp->max_key_size); } - +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) static int smp_c1(const uint8_t k[16], const uint8_t r[16], const uint8_t preq[7], const uint8_t pres[7], const bt_addr_le_t *ia, const bt_addr_le_t *ra, @@ -891,6 +891,7 @@ static int smp_c1(const uint8_t k[16], const uint8_t r[16], return le_encrypt(k, enc_data, enc_data); } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ static uint8_t smp_send_pairing_confirm(struct bt_smp *smp) { @@ -939,6 +940,7 @@ static uint8_t smp_send_pairing_confirm(struct bt_smp *smp) return 0; } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) static void legacy_distribute_keys(struct bt_smp *smp) { struct bt_conn *conn = smp->chan.conn; @@ -989,6 +991,7 @@ static void legacy_distribute_keys(struct bt_smp *smp) smp_send(smp, buf); } } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ static void bt_smp_distribute_keys(struct bt_smp *smp) { @@ -1000,10 +1003,12 @@ static void bt_smp_distribute_keys(struct bt_smp *smp) return; } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) /* Distribute legacy pairing specific keys */ if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { legacy_distribute_keys(smp); } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ #if defined(CONFIG_BLUETOOTH_SIGNING) if (smp->local_dist & BT_SMP_DIST_SIGN) { @@ -1032,6 +1037,7 @@ static void bt_smp_distribute_keys(struct bt_smp *smp) #endif /* CONFIG_BLUETOOTH_SIGNING */ } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) static int smp_s1(const uint8_t k[16], const uint8_t r1[16], const uint8_t r2[16], uint8_t out[16]) { @@ -1337,6 +1343,17 @@ static uint8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf) return 0; } +#else +static uint8_t smp_encrypt_info(struct bt_smp *smp, struct net_buf *buf) +{ + return BT_SMP_ERR_CMD_NOTSUPP; +} + +static uint8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf) +{ + return BT_SMP_ERR_CMD_NOTSUPP; +} +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ #if defined(CONFIG_BLUETOOTH_CENTRAL) static uint8_t legacy_pairing_rsp(struct bt_smp *smp, uint8_t remote_io) @@ -1523,15 +1540,23 @@ static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf) smp->prsp[0] = BT_SMP_CMD_PAIRING_RSP; memcpy(smp->prsp + 1, rsp, sizeof(*rsp)); + smp->method = get_pair_method(smp, req->io_capability); + +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC) || + smp->method == JUST_WORKS) { + return BT_SMP_ERR_AUTH_REQUIREMENTS; + } +#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */ smp_send(smp, rsp_buf); atomic_set_bit(&smp->flags, SMP_FLAG_PAIRING); +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { return legacy_pairing_req(smp, req->io_capability); } - - smp->method = get_pair_method(smp, req->io_capability); +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ return 0; } @@ -1650,11 +1675,21 @@ static uint8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf) } if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + return BT_SMP_ERR_AUTH_REQUIREMENTS; +#else return legacy_pairing_rsp(smp, rsp->io_capability); +#endif /* CONFIG_BLUETOOTH_SMP_SC_ONLY */ } smp->method = get_pair_method(smp, rsp->io_capability); +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (smp->method == JUST_WORKS) { + return BT_SMP_ERR_AUTH_REQUIREMENTS; + } +#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */ + smp->local_dist &= SEND_KEYS_SC; smp->remote_dist &= RECV_KEYS_SC; @@ -1689,9 +1724,11 @@ static uint8_t smp_pairing_confirm(struct bt_smp *smp, struct net_buf *buf) #endif /* CONFIG_BLUETOOTH_CENTRAL */ #if defined(CONFIG_BLUETOOTH_PERIPHERAL) +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { return legacy_pairing_confirm(smp); } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ switch (smp->method) { case PASSKEY_DISPLAY: @@ -1942,9 +1979,11 @@ static uint8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf) memcpy(smp->rrnd, req->val, sizeof(smp->rrnd)); +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { return legacy_pairing_random(smp); } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ #if defined(CONFIG_BLUETOOTH_CENTRAL) if (smp->chan.conn->role == BT_HCI_ROLE_MASTER) { @@ -2070,6 +2109,8 @@ static uint8_t smp_pairing_failed(struct bt_smp *smp, struct net_buf *buf) return 0; } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) +#endif static uint8_t smp_ident_info(struct bt_smp *smp, struct net_buf *buf) { struct bt_conn *conn = smp->chan.conn; @@ -3152,10 +3193,12 @@ void bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) return; } +#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { legacy_passkey_entry(smp, passkey); return; } +#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */ smp->passkey = sys_cpu_to_le32(passkey); @@ -3377,12 +3420,18 @@ int bt_smp_init(void) .accept = bt_smp_accept, }; + sc_supported = le_sc_supported(); +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (!sc_supported) { + BT_ERR("SC Only Mode selected but LE SC not supported"); + return -ENOENT; + } +#endif /* CONFIG_BLUETOOTH_SMP_SC_ONLY */ + net_buf_pool_init(smp_pool); bt_l2cap_fixed_chan_register(&chan); - sc_supported = le_sc_supported(); - BT_DBG("LE SC %s", sc_supported ? "enabled" : "disabled"); return smp_self_test();