* [PATCH 01/49] Bluetooth: Add basic SMP defines for LE Secure Connections
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
@ 2014-12-03 15:01 ` Johan Hedberg
2014-12-03 15:01 ` [PATCH 02/49] Bluetooth: Make auth_req mask dependent on SC enabled or not Johan Hedberg
` (48 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:01 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds basic SMP defines for commands, error codes and PDU
definitions for the LE Secure Connections feature.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.h | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index f76083b85005..7c3c351909f5 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -50,10 +50,13 @@ struct smp_cmd_pairing {
#define SMP_DIST_ENC_KEY 0x01
#define SMP_DIST_ID_KEY 0x02
#define SMP_DIST_SIGN 0x04
+#define SMP_DIST_LINK_KEY 0x08
#define SMP_AUTH_NONE 0x00
#define SMP_AUTH_BONDING 0x01
#define SMP_AUTH_MITM 0x04
+#define SMP_AUTH_SC 0x08
+#define SMP_AUTH_KEYPRESS 0x10
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct smp_cmd_pairing_confirm {
@@ -102,7 +105,23 @@ struct smp_cmd_security_req {
__u8 auth_req;
} __packed;
-#define SMP_CMD_MAX 0x0b
+#define SMP_CMD_PUBLIC_KEY 0x0c
+struct smp_cmd_public_key {
+ __u8 x[32];
+ __u8 y[32];
+} __packed;
+
+#define SMP_CMD_DHKEY_CHECK 0x0d
+struct smp_cmd_dhkey_check {
+ __u8 e[16];
+} __packed;
+
+#define SMP_CMD_KEYPRESS_NOTIFY 0x0e
+struct smp_cmd_keypress_notify {
+ __u8 value;
+} __packed;
+
+#define SMP_CMD_MAX 0x0e
#define SMP_PASSKEY_ENTRY_FAILED 0x01
#define SMP_OOB_NOT_AVAIL 0x02
@@ -114,6 +133,10 @@ struct smp_cmd_security_req {
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
#define SMP_INVALID_PARAMS 0x0a
+#define SMP_DHKEY_CHECK_FAILED 0x0b
+#define SMP_NUMERIC_COMP_FAILED 0x0c
+#define SMP_BREDR_PAIRING_IN_PROGRESS 0x0d
+#define SMP_CROSS_TRANSP_NOT_ALLOWED 0x0e
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 02/49] Bluetooth: Make auth_req mask dependent on SC enabled or not
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
2014-12-03 15:01 ` [PATCH 01/49] Bluetooth: Add basic SMP defines for LE Secure Connections Johan Hedberg
@ 2014-12-03 15:01 ` Johan Hedberg
2014-12-03 15:01 ` [PATCH 03/49] Bluetooth: Add SMP flag for SC and set it when necessary Johan Hedberg
` (47 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:01 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
If we haven't enabled SC support on our side we should use the same mask
for the authentication requirement as we were using before SC support
was added, otherwise we should use the extended mask for SC.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 069b76e03b57..bfa839eed89b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -35,8 +35,9 @@
#define SMP_TIMEOUT msecs_to_jiffies(30000)
-#define AUTH_REQ_MASK 0x07
-#define KEY_DIST_MASK 0x07
+#define AUTH_REQ_MASK(dev) (test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \
+ 0x1f : 0x07)
+#define KEY_DIST_MASK 0x07
enum {
SMP_FLAG_TK_VALID,
@@ -332,7 +333,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
req->init_key_dist = local_dist;
req->resp_key_dist = remote_dist;
- req->auth_req = (authreq & AUTH_REQ_MASK);
+ req->auth_req = (authreq & AUTH_REQ_MASK(hdev));
smp->remote_key_dist = remote_dist;
return;
@@ -343,7 +344,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
rsp->init_key_dist = req->init_key_dist & remote_dist;
rsp->resp_key_dist = req->resp_key_dist & local_dist;
- rsp->auth_req = (authreq & AUTH_REQ_MASK);
+ rsp->auth_req = (authreq & AUTH_REQ_MASK(hdev));
smp->remote_key_dist = rsp->init_key_dist;
}
@@ -942,7 +943,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return SMP_UNSPECIFIED;
/* We didn't start the pairing, so match remote */
- auth = req->auth_req & AUTH_REQ_MASK;
+ auth = req->auth_req & AUTH_REQ_MASK(hdev);
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
(auth & SMP_AUTH_BONDING))
@@ -997,6 +998,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_dev *hdev = conn->hcon->hdev;
u8 key_size, auth;
int ret;
@@ -1016,7 +1018,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
- auth = rsp->auth_req & AUTH_REQ_MASK;
+ auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
/* If we need MITM check that it can be achieved */
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
@@ -1151,6 +1153,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_cmd_security_req *rp = (void *) skb->data;
struct smp_cmd_pairing cp;
struct hci_conn *hcon = conn->hcon;
+ struct hci_dev *hdev = hcon->hdev;
struct smp_chan *smp;
u8 sec_level, auth;
@@ -1162,7 +1165,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (hcon->role != HCI_ROLE_MASTER)
return SMP_CMD_NOTSUPP;
- auth = rp->auth_req & AUTH_REQ_MASK;
+ auth = rp->auth_req & AUTH_REQ_MASK(hdev);
if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 03/49] Bluetooth: Add SMP flag for SC and set it when necessary.
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
2014-12-03 15:01 ` [PATCH 01/49] Bluetooth: Add basic SMP defines for LE Secure Connections Johan Hedberg
2014-12-03 15:01 ` [PATCH 02/49] Bluetooth: Make auth_req mask dependent on SC enabled or not Johan Hedberg
@ 2014-12-03 15:01 ` Johan Hedberg
2014-12-03 15:01 ` [PATCH 04/49] Bluetooth: Update SMP security level to/from auth_req for SC Johan Hedberg
` (46 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:01 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a new SMP flag for tracking whether Secure Connections
is in use and sets the flag when both remote and local side have elected
to use Secure Connections.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index bfa839eed89b..3808ade96d08 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -45,6 +45,7 @@ enum {
SMP_FLAG_MITM_AUTH,
SMP_FLAG_COMPLETE,
SMP_FLAG_INITIATOR,
+ SMP_FLAG_SC,
};
struct smp_chan {
@@ -973,6 +974,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
build_pairing_cmd(conn, req, &rsp, auth);
+ if (rsp.auth_req & SMP_AUTH_SC)
+ set_bit(SMP_FLAG_SC, &smp->flags);
+
key_size = min(req->max_key_size, rsp.max_key_size);
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
@@ -1020,6 +1024,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
+ if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC))
+ set_bit(SMP_FLAG_SC, &smp->flags);
+
/* If we need MITM check that it can be achieved */
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
u8 method;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 04/49] Bluetooth: Update SMP security level to/from auth_req for SC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (2 preceding siblings ...)
2014-12-03 15:01 ` [PATCH 03/49] Bluetooth: Add SMP flag for SC and set it when necessary Johan Hedberg
@ 2014-12-03 15:01 ` Johan Hedberg
2014-12-03 15:01 ` [PATCH 05/49] Bluetooth: Add mgmt support for LE Secure Connections LTK types Johan Hedberg
` (45 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:01 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch updates the functions which map the SMP authentication
request to a security level and vice-versa to take into account the
Secure Connections feature.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3808ade96d08..4ecbf2774fbd 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -284,17 +284,22 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
schedule_delayed_work(&smp->security_timer, SMP_TIMEOUT);
}
-static __u8 authreq_to_seclevel(__u8 authreq)
+static u8 authreq_to_seclevel(u8 authreq)
{
- if (authreq & SMP_AUTH_MITM)
- return BT_SECURITY_HIGH;
- else
+ if (authreq & SMP_AUTH_MITM) {
+ if (authreq & SMP_AUTH_SC)
+ return BT_SECURITY_FIPS;
+ else
+ return BT_SECURITY_HIGH;
+ } else {
return BT_SECURITY_MEDIUM;
+ }
}
static __u8 seclevel_to_authreq(__u8 sec_level)
{
switch (sec_level) {
+ case BT_SECURITY_FIPS:
case BT_SECURITY_HIGH:
return SMP_AUTH_MITM | SMP_AUTH_BONDING;
case BT_SECURITY_MEDIUM:
@@ -1026,6 +1031,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC))
set_bit(SMP_FLAG_SC, &smp->flags);
+ else if (conn->hcon->pending_sec_level > BT_SECURITY_HIGH)
+ conn->hcon->pending_sec_level = BT_SECURITY_HIGH;
/* If we need MITM check that it can be achieved */
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
@@ -1255,6 +1262,9 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
authreq = seclevel_to_authreq(sec_level);
+ if (test_bit(HCI_SC_ENABLED, &hcon->hdev->dev_flags))
+ authreq |= SMP_AUTH_SC;
+
/* Require MITM if IO Capability allows or the security level
* requires it.
*/
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 05/49] Bluetooth: Add mgmt support for LE Secure Connections LTK types
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (3 preceding siblings ...)
2014-12-03 15:01 ` [PATCH 04/49] Bluetooth: Update SMP security level to/from auth_req for SC Johan Hedberg
@ 2014-12-03 15:01 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 06/49] Bluetooth: Set the correct security level for SC LTKs Johan Hedberg
` (44 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:01 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
We need a dedicated LTK type for LTK resulting from a Secure Connections
based SMP pairing. This patch adds a new define for it and ensures that
both the New LTK event as well as the Load LTKs command supports it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/mgmt.h | 3 +++
net/bluetooth/mgmt.c | 33 ++++++++++++++++++++++++++-------
net/bluetooth/smp.h | 13 +++++++++++++
3 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index b391fd663468..9b382ea34fd9 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -184,6 +184,9 @@ struct mgmt_cp_load_link_keys {
#define MGMT_LTK_UNAUTHENTICATED 0x00
#define MGMT_LTK_AUTHENTICATED 0x01
+#define MGMT_LTK_P256_UNAUTH 0x02
+#define MGMT_LTK_P256_AUTH 0x03
+#define MGMT_LTK_P256_DEBUG 0x04
struct mgmt_ltk_info {
struct mgmt_addr_info addr;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index cbeef5f62f3b..7974a39a42d9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4910,18 +4910,26 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
else
addr_type = ADDR_LE_DEV_RANDOM;
- if (key->master)
- type = SMP_LTK;
- else
- type = SMP_LTK_SLAVE;
-
switch (key->type) {
case MGMT_LTK_UNAUTHENTICATED:
authenticated = 0x00;
+ type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
break;
case MGMT_LTK_AUTHENTICATED:
authenticated = 0x01;
+ type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
+ break;
+ case MGMT_LTK_P256_UNAUTH:
+ authenticated = 0x00;
+ type = SMP_LTK_P256;
+ break;
+ case MGMT_LTK_P256_AUTH:
+ authenticated = 0x01;
+ type = SMP_LTK_P256;
break;
+ case MGMT_LTK_P256_DEBUG:
+ authenticated = 0x00;
+ type = SMP_LTK_P256_DEBUG;
default:
continue;
}
@@ -6101,8 +6109,19 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
static u8 mgmt_ltk_type(struct smp_ltk *ltk)
{
- if (ltk->authenticated)
- return MGMT_LTK_AUTHENTICATED;
+ switch (ltk->type) {
+ case SMP_LTK:
+ case SMP_LTK_SLAVE:
+ if (ltk->authenticated)
+ return MGMT_LTK_AUTHENTICATED;
+ return MGMT_LTK_UNAUTHENTICATED;
+ case SMP_LTK_P256:
+ if (ltk->authenticated)
+ return MGMT_LTK_P256_AUTH;
+ return MGMT_LTK_P256_UNAUTH;
+ case SMP_LTK_P256_DEBUG:
+ return MGMT_LTK_P256_DEBUG;
+ }
return MGMT_LTK_UNAUTHENTICATED;
}
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 7c3c351909f5..81d24c0ea08b 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -146,8 +146,21 @@ enum {
SMP_STK,
SMP_LTK,
SMP_LTK_SLAVE,
+ SMP_LTK_P256,
+ SMP_LTK_P256_DEBUG,
};
+static inline bool smp_ltk_is_sc(struct smp_ltk *key)
+{
+ switch (key->type) {
+ case SMP_LTK_P256:
+ case SMP_LTK_P256_DEBUG:
+ return true;
+ }
+
+ return false;
+}
+
static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
{
if (key->authenticated)
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 06/49] Bluetooth: Set the correct security level for SC LTKs
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (4 preceding siblings ...)
2014-12-03 15:01 ` [PATCH 05/49] Bluetooth: Add mgmt support for LE Secure Connections LTK types Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 07/49] Bluetooth: Use custom macro for testing BR/EDR SC enabled Johan Hedberg
` (43 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
When the looked-up LTK is one generated by Secure Connections pairing
the security level it gives is BT_SECURITY_FIPS. This patch updates the
LTK request event handler to correctly set this level.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 81d24c0ea08b..f955d6b7ceb2 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -163,8 +163,12 @@ static inline bool smp_ltk_is_sc(struct smp_ltk *key)
static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
{
- if (key->authenticated)
- return BT_SECURITY_HIGH;
+ if (key->authenticated) {
+ if (smp_ltk_is_sc(key))
+ return BT_SECURITY_FIPS;
+ else
+ return BT_SECURITY_HIGH;
+ }
return BT_SECURITY_MEDIUM;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 07/49] Bluetooth: Use custom macro for testing BR/EDR SC enabled
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (5 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 06/49] Bluetooth: Set the correct security level for SC LTKs Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 08/49] Bluetooth: Add mgmt_set_secure_conn support for any LE adapter Johan Hedberg
` (42 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Since the HCI_SC_ENABLED flag will also be used for controllers without
BR/EDR Secure Connections support whenever we need to check specifically
for SC for BR/EDR we also need to check that the controller actually
supports it. This patch adds a convenience macro for check all the
necessary conditions and converts the places in the code that need it to
use it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 3 +++
net/bluetooth/hci_core.c | 4 +---
net/bluetooth/hci_event.c | 2 +-
net/bluetooth/mgmt.c | 5 ++---
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 396c09840fdf..7f08ea36d246 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -999,6 +999,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
!test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+#define bredr_sc_enabled(dev) ((lmp_sc_capable(dev) || \
+ test_bit(HCI_FORCE_SC, &(dev)->dbg_flags)) && \
+ test_bit(HCI_SC_ENABLED, &(dev)->dev_flags))
/* ----- HCI protocols ----- */
#define HCI_PROTO_DEFER 0x01
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5c319a49a5a4..2586e405adb3 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1734,9 +1734,7 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
/* Enable Secure Connections if supported and configured */
- if ((lmp_sc_capable(hdev) ||
- test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) &&
- test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+ if (bredr_sc_enabled(hdev)) {
u8 support = 0x01;
hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
sizeof(support), &support);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d76d4f821189..f980fc46ea5e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4027,7 +4027,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
if (data) {
- if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+ if (bredr_sc_enabled(hdev)) {
struct hci_cp_remote_oob_ext_data_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7974a39a42d9..868769543d83 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3562,7 +3562,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}
- if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
+ if (bredr_sc_enabled(hdev))
err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
0, NULL);
else
@@ -6803,8 +6803,7 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
mgmt_status(status));
} else {
- if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
- hash256 && rand256) {
+ if (bredr_sc_enabled(hdev) && hash256 && rand256) {
struct mgmt_rp_read_local_oob_ext_data rp;
memcpy(rp.hash192, hash192, sizeof(rp.hash192));
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 08/49] Bluetooth: Add mgmt_set_secure_conn support for any LE adapter
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (6 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 07/49] Bluetooth: Use custom macro for testing BR/EDR SC enabled Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 09/49] Bluetooth: Update LTK lookup to correctly deal with SC LTKs Johan Hedberg
` (41 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Since LE Secure Connections is a purely host-side feature we should
offer the Secure Connections mgmt setting for any adapter with LE
support. This patch updates the supported settings value and the
set_secure_conn command handler accordingly.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 868769543d83..6e8165364b7f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -574,6 +574,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (lmp_le_capable(hdev)) {
settings |= MGMT_SETTING_LE;
settings |= MGMT_SETTING_ADVERTISING;
+ settings |= MGMT_SETTING_SECURE_CONN;
settings |= MGMT_SETTING_PRIVACY;
}
@@ -4572,18 +4573,13 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
{
struct mgmt_mode *cp = data;
struct pending_cmd *cmd;
- u8 val, status;
+ u8 val;
int err;
BT_DBG("request for %s", hdev->name);
- status = mgmt_bredr_support(hdev);
- if (status)
- return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
- status);
-
- if (!lmp_sc_capable(hdev) &&
- !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
+ !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_NOT_SUPPORTED);
@@ -4593,7 +4589,10 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev);
- if (!hdev_is_powered(hdev)) {
+ if (!hdev_is_powered(hdev) ||
+ (!lmp_sc_capable(hdev) &&
+ !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
+ !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
bool changed;
if (cp->val) {
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 09/49] Bluetooth: Update LTK lookup to correctly deal with SC LTKs
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (7 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 08/49] Bluetooth: Add mgmt_set_secure_conn support for any LE adapter Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 10/49] Bluetooth: Remove unused hci_find_ltk function Johan Hedberg
` (40 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
LTKs derived from Secure Connections based pairing are symmetric, i.e.
they should match both master and slave role. This patch updates the LTK
lookup functions to ignore the desired role when dealing with SC LTKs.
Furthermore, with Secure Connections the EDiv and Rand values are not
used and should always be set to zero. This patch updates the LTK lookup
to first use the bdaddr as key and then do the necessary verifications
of EDiv and Rand based on whether the found LTK is for SC or not.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/hci_core.c | 30 +++++++++++++++++++++++-------
net/bluetooth/hci_event.c | 15 +++++++++++++--
2 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2586e405adb3..e091e8ffeb8e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3195,11 +3195,18 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
if (k->ediv != ediv || k->rand != rand)
continue;
- if (ltk_role(k->type) != role)
- continue;
+ if (smp_ltk_is_sc(k)) {
+ if (k->type == SMP_LTK_P256_DEBUG &&
+ !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
+ continue;
+ rcu_read_unlock();
+ return k;
+ }
- rcu_read_unlock();
- return k;
+ if (ltk_role(k->type) == role) {
+ rcu_read_unlock();
+ return k;
+ }
}
rcu_read_unlock();
@@ -3213,9 +3220,18 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
rcu_read_lock();
list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
- if (addr_type == k->bdaddr_type &&
- bacmp(bdaddr, &k->bdaddr) == 0 &&
- ltk_role(k->type) == role) {
+ if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
+ continue;
+
+ if (smp_ltk_is_sc(k)) {
+ if (k->type == SMP_LTK_P256_DEBUG &&
+ !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
+ continue;
+ rcu_read_unlock();
+ return k;
+ }
+
+ if (ltk_role(k->type) == role) {
rcu_read_unlock();
return k;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f980fc46ea5e..0058b545c5ed 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4590,10 +4590,21 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn == NULL)
goto not_found;
- ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
- if (ltk == NULL)
+ ltk = hci_find_ltk_by_addr(hdev, &conn->dst, conn->dst_type,
+ conn->role);
+ if (!ltk)
goto not_found;
+ if (smp_ltk_is_sc(ltk)) {
+ /* With SC both EDiv and Rand are set to zero */
+ if (ev->ediv || ev->rand)
+ goto not_found;
+ } else {
+ /* For non-SC keys check that EDiv and Rand match */
+ if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
+ goto not_found;
+ }
+
memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
cp.handle = cpu_to_le16(conn->handle);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 10/49] Bluetooth: Remove unused hci_find_ltk function
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (8 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 09/49] Bluetooth: Update LTK lookup to correctly deal with SC LTKs Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 11/49] Bluetooth: Rename hci_find_ltk_by_addr to hci_find_ltk Johan Hedberg
` (39 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Now that LTKs are always looked up based on bdaddr (with EDiv/Rand
checks done after a successful lookup) the hci_find_ltk function is not
needed anymore. This patch removes the function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 2 --
net/bluetooth/hci_core.c | 28 ----------------------------
2 files changed, 30 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7f08ea36d246..b41969b561d8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -921,8 +921,6 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
bdaddr_t *bdaddr, u8 *val, u8 type,
u8 pin_len, bool *persistent);
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
- u8 role);
struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e091e8ffeb8e..cb9bc8e2c58d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3185,34 +3185,6 @@ static u8 ltk_role(u8 type)
return HCI_ROLE_SLAVE;
}
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
- u8 role)
-{
- struct smp_ltk *k;
-
- rcu_read_lock();
- list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
- if (k->ediv != ediv || k->rand != rand)
- continue;
-
- if (smp_ltk_is_sc(k)) {
- if (k->type == SMP_LTK_P256_DEBUG &&
- !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
- continue;
- rcu_read_unlock();
- return k;
- }
-
- if (ltk_role(k->type) == role) {
- rcu_read_unlock();
- return k;
- }
- }
- rcu_read_unlock();
-
- return NULL;
-}
-
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 role)
{
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 11/49] Bluetooth: Rename hci_find_ltk_by_addr to hci_find_ltk
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (9 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 10/49] Bluetooth: Remove unused hci_find_ltk function Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 12/49] Bluetooth: Set link key generation bit if necessary for LE SC Johan Hedberg
` (38 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Now that hci_find_ltk_by_addr is the only LTK lookup function there's no
need to keep the long name anymore. This patch shortens the function
name to simply hci_find_ltk.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 4 ++--
net/bluetooth/hci_core.c | 6 +++---
net/bluetooth/hci_event.c | 3 +--
net/bluetooth/smp.c | 6 ++----
4 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b41969b561d8..90929641d0f0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -924,8 +924,8 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
-struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, u8 role);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type, u8 role);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
void hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cb9bc8e2c58d..6c3220e9484f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3185,8 +3185,8 @@ static u8 ltk_role(u8 type)
return HCI_ROLE_SLAVE;
}
-struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, u8 role)
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type, u8 role)
{
struct smp_ltk *k;
@@ -3313,7 +3313,7 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
struct smp_ltk *key, *old_key;
u8 role = ltk_role(type);
- old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role);
+ old_key = hci_find_ltk(hdev, bdaddr, addr_type, role);
if (old_key)
key = old_key;
else {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0058b545c5ed..34ecbf0b7e5b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4590,8 +4590,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn == NULL)
goto not_found;
- ltk = hci_find_ltk_by_addr(hdev, &conn->dst, conn->dst_type,
- conn->role);
+ ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
if (!ltk)
goto not_found;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 4ecbf2774fbd..0973e37073e2 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1118,8 +1118,7 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
struct smp_ltk *key;
struct hci_conn *hcon = conn->hcon;
- key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
- hcon->role);
+ key = hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role);
if (!key)
return false;
@@ -1152,8 +1151,7 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
*/
if (key_pref == SMP_USE_LTK &&
test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
- hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
- hcon->role))
+ hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role))
return false;
if (hcon->sec_level >= sec_level)
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 12/49] Bluetooth: Set link key generation bit if necessary for LE SC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (10 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 11/49] Bluetooth: Rename hci_find_ltk_by_addr to hci_find_ltk Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 13/49] Bluetooth: Add basic support for AES-CMAC Johan Hedberg
` (37 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Depending on whether Secure Connections is enabled or not we may need to add
the link key generation bit to the key distribution. This patch does the
necessary modifications to the build_pairing_cmd() function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 0973e37073e2..d993d7d4fcc8 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -333,6 +333,16 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
local_dist |= SMP_DIST_ID_KEY;
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+ if ((authreq & SMP_AUTH_SC) &&
+ test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+ local_dist |= SMP_DIST_LINK_KEY;
+ remote_dist |= SMP_DIST_LINK_KEY;
+ }
+ } else {
+ authreq &= ~SMP_AUTH_SC;
+ }
+
if (rsp == NULL) {
req->io_capability = conn->hcon->io_capability;
req->oob_flag = SMP_OOB_NOT_PRESENT;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 13/49] Bluetooth: Add basic support for AES-CMAC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (11 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 12/49] Bluetooth: Set link key generation bit if necessary for LE SC Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 14/49] Bluetooth: Add ECC library for LE Secure Connections Johan Hedberg
` (36 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Most of the LE Secure Connections SMP crypto functions build on top of
the AES-CMAC function. This patch adds access to AES-CMAC in the kernel
crypto subsystem by allocating a crypto_hash handle for it in a similar
way that we have one for AES-CBC.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/Kconfig | 1 +
net/bluetooth/smp.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 5e97a8ff850b..29bcafc41adf 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -10,6 +10,7 @@ menuconfig BT
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_AES
+ select CRYPTO_CMAC
select CRYPTO_ECB
select CRYPTO_SHA256
help
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index d993d7d4fcc8..4fed367da380 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -72,6 +72,7 @@ struct smp_chan {
unsigned long flags;
struct crypto_blkcipher *tfm_aes;
+ struct crypto_hash *tfm_cmac;
};
static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
@@ -396,6 +397,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
kfree(smp->slave_csrk);
crypto_free_blkcipher(smp->tfm_aes);
+ crypto_free_hash(smp->tfm_cmac);
/* If pairing failed clean up any keys we might have */
if (!complete) {
@@ -861,6 +863,14 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
return NULL;
}
+ smp->tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(smp->tfm_cmac)) {
+ BT_ERR("Unable to create CMAC crypto context");
+ crypto_free_blkcipher(smp->tfm_aes);
+ kfree(smp);
+ return NULL;
+ }
+
smp->conn = conn;
chan->data = smp;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 14/49] Bluetooth: Add ECC library for LE Secure Connections
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (12 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 13/49] Bluetooth: Add basic support for AES-CMAC Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 15/49] Bluetooth: Add basic support for sending our LE SC public key Johan Hedberg
` (35 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a simple ECC library that will act as a fundamental
building block for LE Secure Connections. The library has a simple API
consisting of two functions: one for generating a public/private key
pair and another one for generating a Diffie-Hellman key from a local
private key and a remote public key.
The code has been taken from https://github.com/kmackay/easy-ecc and
modified to conform with the kernel coding style.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/Makefile | 2 +-
net/bluetooth/ecc.c | 816 +++++++++++++++++++++++++++++++++++++++++++++++++
net/bluetooth/ecc.h | 54 ++++
3 files changed, 871 insertions(+), 1 deletion(-)
create mode 100644 net/bluetooth/ecc.c
create mode 100644 net/bluetooth/ecc.h
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 886e9aa3ecf1..a5432a6a0ae6 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -13,6 +13,6 @@ bluetooth_6lowpan-y := 6lowpan.o
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
- a2mp.o amp.o
+ a2mp.o amp.o ecc.o
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/bluetooth/ecc.c b/net/bluetooth/ecc.c
new file mode 100644
index 000000000000..e1709f8467ac
--- /dev/null
+++ b/net/bluetooth/ecc.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2013, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/random.h>
+
+#include "ecc.h"
+
+/* 256-bit curve */
+#define ECC_BYTES 32
+
+#define MAX_TRIES 16
+
+/* Number of u64's needed */
+#define NUM_ECC_DIGITS (ECC_BYTES / 8)
+
+struct ecc_point {
+ u64 x[NUM_ECC_DIGITS];
+ u64 y[NUM_ECC_DIGITS];
+};
+
+typedef struct {
+ u64 m_low;
+ u64 m_high;
+} uint128_t;
+
+#define CURVE_P_32 { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
+ 0x0000000000000000ull, 0xFFFFFFFF00000001ull }
+
+#define CURVE_G_32 { \
+ { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull, \
+ 0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }, \
+ { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull, \
+ 0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull } \
+}
+
+#define CURVE_N_32 { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull, \
+ 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
+
+static u64 curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
+static struct ecc_point curve_g = CURVE_G_32;
+static u64 curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
+
+static void vli_clear(u64 *vli)
+{
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++)
+ vli[i] = 0;
+}
+
+/* Returns true if vli == 0, false otherwise. */
+static bool vli_is_zero(const u64 *vli)
+{
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ if (vli[i])
+ return false;
+ }
+
+ return true;
+}
+
+/* Returns nonzero if bit bit of vli is set. */
+static u64 vli_test_bit(const u64 *vli, unsigned int bit)
+{
+ return (vli[bit / 64] & ((u64) 1 << (bit % 64)));
+}
+
+/* Counts the number of 64-bit "digits" in vli. */
+static unsigned int vli_num_digits(const u64 *vli)
+{
+ int i;
+
+ /* Search from the end until we find a non-zero digit.
+ * We do it in reverse because we expect that most digits will
+ * be nonzero.
+ */
+ for (i = NUM_ECC_DIGITS - 1; i >= 0 && vli[i] == 0; i--);
+
+ return (i + 1);
+}
+
+/* Counts the number of bits required for vli. */
+static unsigned int vli_num_bits(const u64 *vli)
+{
+ unsigned int i, num_digits;
+ u64 digit;
+
+ num_digits = vli_num_digits(vli);
+ if (num_digits == 0)
+ return 0;
+
+ digit = vli[num_digits - 1];
+ for (i = 0; digit; i++)
+ digit >>= 1;
+
+ return ((num_digits - 1) * 64 + i);
+}
+
+/* Sets dest = src. */
+static void vli_set(u64 *dest, const u64 *src)
+{
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++)
+ dest[i] = src[i];
+}
+
+/* Returns sign of left - right. */
+static int vli_cmp(const u64 *left, const u64 *right)
+{
+ int i;
+
+ for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
+ if (left[i] > right[i])
+ return 1;
+ else if (left[i] < right[i])
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Computes result = in << c, returning carry. Can modify in place
+ * (if result == in). 0 < shift < 64.
+ */
+static u64 vli_lshift(u64 *result, const u64 *in,
+ unsigned int shift)
+{
+ u64 carry = 0;
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ u64 temp = in[i];
+
+ result[i] = (temp << shift) | carry;
+ carry = temp >> (64 - shift);
+ }
+
+ return carry;
+}
+
+/* Computes vli = vli >> 1. */
+static void vli_rshift1(u64 *vli)
+{
+ u64 *end = vli;
+ u64 carry = 0;
+
+ vli += NUM_ECC_DIGITS;
+
+ while (vli-- > end) {
+ u64 temp = *vli;
+ *vli = (temp >> 1) | carry;
+ carry = temp << 63;
+ }
+}
+
+/* Computes result = left + right, returning carry. Can modify in place. */
+static u64 vli_add(u64 *result, const u64 *left,
+ const u64 *right)
+{
+ u64 carry = 0;
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ u64 sum;
+
+ sum = left[i] + right[i] + carry;
+ if (sum != left[i])
+ carry = (sum < left[i]);
+
+ result[i] = sum;
+ }
+
+ return carry;
+}
+
+/* Computes result = left - right, returning borrow. Can modify in place. */
+static u64 vli_sub(u64 *result, const u64 *left, const u64 *right)
+{
+ u64 borrow = 0;
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ u64 diff;
+
+ diff = left[i] - right[i] - borrow;
+ if (diff != left[i])
+ borrow = (diff > left[i]);
+
+ result[i] = diff;
+ }
+
+ return borrow;
+}
+
+static uint128_t mul_64_64(u64 left, u64 right)
+{
+ u64 a0 = left & 0xffffffffull;
+ u64 a1 = left >> 32;
+ u64 b0 = right & 0xffffffffull;
+ u64 b1 = right >> 32;
+ u64 m0 = a0 * b0;
+ u64 m1 = a0 * b1;
+ u64 m2 = a1 * b0;
+ u64 m3 = a1 * b1;
+ uint128_t result;
+
+ m2 += (m0 >> 32);
+ m2 += m1;
+
+ /* Overflow */
+ if (m2 < m1)
+ m3 += 0x100000000ull;
+
+ result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
+ result.m_high = m3 + (m2 >> 32);
+
+ return result;
+}
+
+static uint128_t add_128_128(uint128_t a, uint128_t b)
+{
+ uint128_t result;
+
+ result.m_low = a.m_low + b.m_low;
+ result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
+
+ return result;
+}
+
+static void vli_mult(u64 *result, const u64 *left, const u64 *right)
+{
+ uint128_t r01 = { 0, 0 };
+ u64 r2 = 0;
+ unsigned int i, k;
+
+ /* Compute each digit of result in sequence, maintaining the
+ * carries.
+ */
+ for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
+ unsigned int min;
+
+ if (k < NUM_ECC_DIGITS)
+ min = 0;
+ else
+ min = (k + 1) - NUM_ECC_DIGITS;
+
+ for (i = min; i <= k && i < NUM_ECC_DIGITS; i++) {
+ uint128_t product;
+
+ product = mul_64_64(left[i], right[k - i]);
+
+ r01 = add_128_128(r01, product);
+ r2 += (r01.m_high < product.m_high);
+ }
+
+ result[k] = r01.m_low;
+ r01.m_low = r01.m_high;
+ r01.m_high = r2;
+ r2 = 0;
+ }
+
+ result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
+}
+
+static void vli_square(u64 *result, const u64 *left)
+{
+ uint128_t r01 = { 0, 0 };
+ u64 r2 = 0;
+ int i, k;
+
+ for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
+ unsigned int min;
+
+ if (k < NUM_ECC_DIGITS)
+ min = 0;
+ else
+ min = (k + 1) - NUM_ECC_DIGITS;
+
+ for (i = min; i <= k && i <= k - i; i++) {
+ uint128_t product;
+
+ product = mul_64_64(left[i], left[k - i]);
+
+ if (i < k - i) {
+ r2 += product.m_high >> 63;
+ product.m_high = (product.m_high << 1) |
+ (product.m_low >> 63);
+ product.m_low <<= 1;
+ }
+
+ r01 = add_128_128(r01, product);
+ r2 += (r01.m_high < product.m_high);
+ }
+
+ result[k] = r01.m_low;
+ r01.m_low = r01.m_high;
+ r01.m_high = r2;
+ r2 = 0;
+ }
+
+ result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
+}
+
+/* Computes result = (left + right) % mod.
+ * Assumes that left < mod and right < mod, result != mod.
+ */
+static void vli_mod_add(u64 *result, const u64 *left, const u64 *right,
+ const u64 *mod)
+{
+ u64 carry;
+
+ carry = vli_add(result, left, right);
+
+ /* result > mod (result = mod + remainder), so subtract mod to
+ * get remainder.
+ */
+ if (carry || vli_cmp(result, mod) >= 0)
+ vli_sub(result, result, mod);
+}
+
+/* Computes result = (left - right) % mod.
+ * Assumes that left < mod and right < mod, result != mod.
+ */
+static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
+ const u64 *mod)
+{
+ u64 borrow = vli_sub(result, left, right);
+
+ /* In this case, p_result == -diff == (max int) - diff.
+ * Since -x % d == d - x, we can get the correct result from
+ * result + mod (with overflow).
+ */
+ if (borrow)
+ vli_add(result, result, mod);
+}
+
+/* Computes result = product % curve_p
+ from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void vli_mmod_fast(u64 *result, const u64 *product)
+{
+ u64 tmp[NUM_ECC_DIGITS];
+ int carry;
+
+ /* t */
+ vli_set(result, product);
+
+ /* s1 */
+ tmp[0] = 0;
+ tmp[1] = product[5] & 0xffffffff00000000ull;
+ tmp[2] = product[6];
+ tmp[3] = product[7];
+ carry = vli_lshift(tmp, tmp, 1);
+ carry += vli_add(result, result, tmp);
+
+ /* s2 */
+ tmp[1] = product[6] << 32;
+ tmp[2] = (product[6] >> 32) | (product[7] << 32);
+ tmp[3] = product[7] >> 32;
+ carry += vli_lshift(tmp, tmp, 1);
+ carry += vli_add(result, result, tmp);
+
+ /* s3 */
+ tmp[0] = product[4];
+ tmp[1] = product[5] & 0xffffffff;
+ tmp[2] = 0;
+ tmp[3] = product[7];
+ carry += vli_add(result, result, tmp);
+
+ /* s4 */
+ tmp[0] = (product[4] >> 32) | (product[5] << 32);
+ tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
+ tmp[2] = product[7];
+ tmp[3] = (product[6] >> 32) | (product[4] << 32);
+ carry += vli_add(result, result, tmp);
+
+ /* d1 */
+ tmp[0] = (product[5] >> 32) | (product[6] << 32);
+ tmp[1] = (product[6] >> 32);
+ tmp[2] = 0;
+ tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
+ carry -= vli_sub(result, result, tmp);
+
+ /* d2 */
+ tmp[0] = product[6];
+ tmp[1] = product[7];
+ tmp[2] = 0;
+ tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
+ carry -= vli_sub(result, result, tmp);
+
+ /* d3 */
+ tmp[0] = (product[6] >> 32) | (product[7] << 32);
+ tmp[1] = (product[7] >> 32) | (product[4] << 32);
+ tmp[2] = (product[4] >> 32) | (product[5] << 32);
+ tmp[3] = (product[6] << 32);
+ carry -= vli_sub(result, result, tmp);
+
+ /* d4 */
+ tmp[0] = product[7];
+ tmp[1] = product[4] & 0xffffffff00000000ull;
+ tmp[2] = product[5];
+ tmp[3] = product[6] & 0xffffffff00000000ull;
+ carry -= vli_sub(result, result, tmp);
+
+ if (carry < 0) {
+ do {
+ carry += vli_add(result, result, curve_p);
+ } while (carry < 0);
+ } else {
+ while (carry || vli_cmp(curve_p, result) != 1)
+ carry -= vli_sub(result, result, curve_p);
+ }
+}
+
+/* Computes result = (left * right) % curve_p. */
+static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right)
+{
+ u64 product[2 * NUM_ECC_DIGITS];
+
+ vli_mult(product, left, right);
+ vli_mmod_fast(result, product);
+}
+
+/* Computes result = left^2 % curve_p. */
+static void vli_mod_square_fast(u64 *result, const u64 *left)
+{
+ u64 product[2 * NUM_ECC_DIGITS];
+
+ vli_square(product, left);
+ vli_mmod_fast(result, product);
+}
+
+#define EVEN(vli) (!(vli[0] & 1))
+/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
+ * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
+ * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
+ */
+static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod)
+{
+ u64 a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS];
+ u64 u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
+ u64 carry;
+ int cmp_result;
+
+ if (vli_is_zero(input)) {
+ vli_clear(result);
+ return;
+ }
+
+ vli_set(a, input);
+ vli_set(b, mod);
+ vli_clear(u);
+ u[0] = 1;
+ vli_clear(v);
+
+ while ((cmp_result = vli_cmp(a, b)) != 0) {
+ carry = 0;
+
+ if (EVEN(a)) {
+ vli_rshift1(a);
+
+ if (!EVEN(u))
+ carry = vli_add(u, u, mod);
+
+ vli_rshift1(u);
+ if (carry)
+ u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
+ } else if (EVEN(b)) {
+ vli_rshift1(b);
+
+ if (!EVEN(v))
+ carry = vli_add(v, v, mod);
+
+ vli_rshift1(v);
+ if (carry)
+ v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
+ } else if (cmp_result > 0) {
+ vli_sub(a, a, b);
+ vli_rshift1(a);
+
+ if (vli_cmp(u, v) < 0)
+ vli_add(u, u, mod);
+
+ vli_sub(u, u, v);
+ if (!EVEN(u))
+ carry = vli_add(u, u, mod);
+
+ vli_rshift1(u);
+ if (carry)
+ u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
+ } else {
+ vli_sub(b, b, a);
+ vli_rshift1(b);
+
+ if (vli_cmp(v, u) < 0)
+ vli_add(v, v, mod);
+
+ vli_sub(v, v, u);
+ if (!EVEN(v))
+ carry = vli_add(v, v, mod);
+
+ vli_rshift1(v);
+ if (carry)
+ v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
+ }
+ }
+
+ vli_set(result, u);
+}
+
+/* ------ Point operations ------ */
+
+/* Returns true if p_point is the point at infinity, false otherwise. */
+static bool ecc_point_is_zero(const struct ecc_point *point)
+{
+ return (vli_is_zero(point->x) && vli_is_zero(point->y));
+}
+
+/* Point multiplication algorithm using Montgomery's ladder with co-Z
+ * coordinates. From http://eprint.iacr.org/2011/338.pdf
+ */
+
+/* Double in place */
+static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1)
+{
+ /* t1 = x, t2 = y, t3 = z */
+ u64 t4[NUM_ECC_DIGITS];
+ u64 t5[NUM_ECC_DIGITS];
+
+ if (vli_is_zero(z1))
+ return;
+
+ vli_mod_square_fast(t4, y1); /* t4 = y1^2 */
+ vli_mod_mult_fast(t5, x1, t4); /* t5 = x1*y1^2 = A */
+ vli_mod_square_fast(t4, t4); /* t4 = y1^4 */
+ vli_mod_mult_fast(y1, y1, z1); /* t2 = y1*z1 = z3 */
+ vli_mod_square_fast(z1, z1); /* t3 = z1^2 */
+
+ vli_mod_add(x1, x1, z1, curve_p); /* t1 = x1 + z1^2 */
+ vli_mod_add(z1, z1, z1, curve_p); /* t3 = 2*z1^2 */
+ vli_mod_sub(z1, x1, z1, curve_p); /* t3 = x1 - z1^2 */
+ vli_mod_mult_fast(x1, x1, z1); /* t1 = x1^2 - z1^4 */
+
+ vli_mod_add(z1, x1, x1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
+ vli_mod_add(x1, x1, z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
+ if (vli_test_bit(x1, 0)) {
+ u64 carry = vli_add(x1, x1, curve_p);
+ vli_rshift1(x1);
+ x1[NUM_ECC_DIGITS - 1] |= carry << 63;
+ } else {
+ vli_rshift1(x1);
+ }
+ /* t1 = 3/2*(x1^2 - z1^4) = B */
+
+ vli_mod_square_fast(z1, x1); /* t3 = B^2 */
+ vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - A */
+ vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
+ vli_mod_sub(t5, t5, z1, curve_p); /* t5 = A - x3 */
+ vli_mod_mult_fast(x1, x1, t5); /* t1 = B * (A - x3) */
+ vli_mod_sub(t4, x1, t4, curve_p); /* t4 = B * (A - x3) - y1^4 = y3 */
+
+ vli_set(x1, z1);
+ vli_set(z1, y1);
+ vli_set(y1, t4);
+}
+
+/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
+static void apply_z(u64 *x1, u64 *y1, u64 *z)
+{
+ u64 t1[NUM_ECC_DIGITS];
+
+ vli_mod_square_fast(t1, z); /* z^2 */
+ vli_mod_mult_fast(x1, x1, t1); /* x1 * z^2 */
+ vli_mod_mult_fast(t1, t1, z); /* z^3 */
+ vli_mod_mult_fast(y1, y1, t1); /* y1 * z^3 */
+}
+
+/* P = (x1, y1) => 2P, (x2, y2) => P' */
+static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2,
+ u64 *p_initial_z)
+{
+ u64 z[NUM_ECC_DIGITS];
+
+ vli_set(x2, x1);
+ vli_set(y2, y1);
+
+ vli_clear(z);
+ z[0] = 1;
+
+ if (p_initial_z)
+ vli_set(z, p_initial_z);
+
+ apply_z(x1, y1, z);
+
+ ecc_point_double_jacobian(x1, y1, z);
+
+ apply_z(x2, y2, z);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ * Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
+ * or P => P', Q => P + Q
+ */
+static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
+{
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ u64 t5[NUM_ECC_DIGITS];
+
+ vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
+ vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
+ vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
+ vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
+ vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
+ vli_mod_square_fast(t5, y2); /* t5 = (y2 - y1)^2 = D */
+
+ vli_mod_sub(t5, t5, x1, curve_p); /* t5 = D - B */
+ vli_mod_sub(t5, t5, x2, curve_p); /* t5 = D - B - C = x3 */
+ vli_mod_sub(x2, x2, x1, curve_p); /* t3 = C - B */
+ vli_mod_mult_fast(y1, y1, x2); /* t2 = y1*(C - B) */
+ vli_mod_sub(x2, x1, t5, curve_p); /* t3 = B - x3 */
+ vli_mod_mult_fast(y2, y2, x2); /* t4 = (y2 - y1)*(B - x3) */
+ vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
+
+ vli_set(x2, t5);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ * Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
+ * or P => P - Q, Q => P + Q
+ */
+static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
+{
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ u64 t5[NUM_ECC_DIGITS];
+ u64 t6[NUM_ECC_DIGITS];
+ u64 t7[NUM_ECC_DIGITS];
+
+ vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
+ vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
+ vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
+ vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
+ vli_mod_add(t5, y2, y1, curve_p); /* t4 = y2 + y1 */
+ vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
+
+ vli_mod_sub(t6, x2, x1, curve_p); /* t6 = C - B */
+ vli_mod_mult_fast(y1, y1, t6); /* t2 = y1 * (C - B) */
+ vli_mod_add(t6, x1, x2, curve_p); /* t6 = B + C */
+ vli_mod_square_fast(x2, y2); /* t3 = (y2 - y1)^2 */
+ vli_mod_sub(x2, x2, t6, curve_p); /* t3 = x3 */
+
+ vli_mod_sub(t7, x1, x2, curve_p); /* t7 = B - x3 */
+ vli_mod_mult_fast(y2, y2, t7); /* t4 = (y2 - y1)*(B - x3) */
+ vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
+
+ vli_mod_square_fast(t7, t5); /* t7 = (y2 + y1)^2 = F */
+ vli_mod_sub(t7, t7, t6, curve_p); /* t7 = x3' */
+ vli_mod_sub(t6, t7, x1, curve_p); /* t6 = x3' - B */
+ vli_mod_mult_fast(t6, t6, t5); /* t6 = (y2 + y1)*(x3' - B) */
+ vli_mod_sub(y1, t6, y1, curve_p); /* t2 = y3' */
+
+ vli_set(x1, t7);
+}
+
+static void ecc_point_mult(struct ecc_point *result,
+ const struct ecc_point *point, u64 *scalar,
+ u64 *initial_z, int num_bits)
+{
+ /* R0 and R1 */
+ u64 rx[2][NUM_ECC_DIGITS];
+ u64 ry[2][NUM_ECC_DIGITS];
+ u64 z[NUM_ECC_DIGITS];
+ int i, nb;
+
+ vli_set(rx[1], point->x);
+ vli_set(ry[1], point->y);
+
+ xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z);
+
+ for (i = num_bits - 2; i > 0; i--) {
+ nb = !vli_test_bit(scalar, i);
+ xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
+ xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
+ }
+
+ nb = !vli_test_bit(scalar, 0);
+ xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
+
+ /* Find final 1/Z value. */
+ vli_mod_sub(z, rx[1], rx[0], curve_p); /* X1 - X0 */
+ vli_mod_mult_fast(z, z, ry[1 - nb]); /* Yb * (X1 - X0) */
+ vli_mod_mult_fast(z, z, point->x); /* xP * Yb * (X1 - X0) */
+ vli_mod_inv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0)) */
+ vli_mod_mult_fast(z, z, point->y); /* yP / (xP * Yb * (X1 - X0)) */
+ vli_mod_mult_fast(z, z, rx[1 - nb]); /* Xb * yP / (xP * Yb * (X1 - X0)) */
+ /* End 1/Z calculation */
+
+ xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
+
+ apply_z(rx[0], ry[0], z);
+
+ vli_set(result->x, rx[0]);
+ vli_set(result->y, ry[0]);
+}
+
+static void ecc_bytes2native(const u8 bytes[ECC_BYTES],
+ u64 native[NUM_ECC_DIGITS])
+{
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ const u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
+
+ native[NUM_ECC_DIGITS - 1 - i] =
+ ((u64) digit[0] << 0) |
+ ((u64) digit[1] << 8) |
+ ((u64) digit[2] << 16) |
+ ((u64) digit[3] << 24) |
+ ((u64) digit[4] << 32) |
+ ((u64) digit[5] << 40) |
+ ((u64) digit[6] << 48) |
+ ((u64) digit[7] << 56);
+ }
+}
+
+static void ecc_native2bytes(const u64 native[NUM_ECC_DIGITS],
+ u8 bytes[ECC_BYTES])
+{
+ int i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
+
+ digit[0] = native[NUM_ECC_DIGITS - 1 - i] >> 0;
+ digit[1] = native[NUM_ECC_DIGITS - 1 - i] >> 8;
+ digit[2] = native[NUM_ECC_DIGITS - 1 - i] >> 16;
+ digit[3] = native[NUM_ECC_DIGITS - 1 - i] >> 24;
+ digit[4] = native[NUM_ECC_DIGITS - 1 - i] >> 32;
+ digit[5] = native[NUM_ECC_DIGITS - 1 - i] >> 40;
+ digit[6] = native[NUM_ECC_DIGITS - 1 - i] >> 48;
+ digit[7] = native[NUM_ECC_DIGITS - 1 - i] >> 56;
+ }
+}
+
+bool ecc_make_key(u8 public_key[64], u8 private_key[32])
+{
+ struct ecc_point pk;
+ u64 priv[NUM_ECC_DIGITS];
+ unsigned int tries = 0;
+
+ do {
+ if (tries++ >= MAX_TRIES)
+ return false;
+
+ get_random_bytes(priv, ECC_BYTES);
+
+ if (vli_is_zero(priv))
+ continue;
+
+ /* Make sure the private key is in the range [1, n-1]. */
+ if (vli_cmp(curve_n, priv) != 1)
+ continue;
+
+ ecc_point_mult(&pk, &curve_g, priv, NULL, vli_num_bits(priv));
+ } while (ecc_point_is_zero(&pk));
+
+ ecc_native2bytes(priv, private_key);
+ ecc_native2bytes(pk.x, public_key);
+ ecc_native2bytes(pk.y, &public_key[32]);
+
+ return true;
+}
+
+bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
+ u8 secret[32])
+{
+ u64 priv[NUM_ECC_DIGITS];
+ u64 rand[NUM_ECC_DIGITS];
+ struct ecc_point product, pk;
+
+ get_random_bytes(rand, ECC_BYTES);
+
+ ecc_bytes2native(public_key, pk.x);
+ ecc_bytes2native(&public_key[32], pk.y);
+ ecc_bytes2native(private_key, priv);
+
+ ecc_point_mult(&product, &pk, priv, rand, vli_num_bits(priv));
+
+ ecc_native2bytes(product.x, secret);
+
+ return !ecc_point_is_zero(&product);
+}
diff --git a/net/bluetooth/ecc.h b/net/bluetooth/ecc.h
new file mode 100644
index 000000000000..8d6a2f4d1905
--- /dev/null
+++ b/net/bluetooth/ecc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Create a public/private key pair.
+ * Outputs:
+ * public_key - Will be filled in with the public key.
+ * private_key - Will be filled in with the private key.
+ *
+ * Returns true if the key pair was generated successfully, false
+ * if an error occurred. The keys are with the LSB first.
+ */
+bool ecc_make_key(u8 public_key[64], u8 private_key[32]);
+
+/* Compute a shared secret given your secret key and someone else's
+ * public key.
+ * Note: It is recommended that you hash the result of ecdh_shared_secret
+ * before using it for symmetric encryption or HMAC.
+ *
+ * Inputs:
+ * public_key - The public key of the remote party
+ * private_key - Your private key.
+ *
+ * Outputs:
+ * secret - Will be filled in with the shared secret value.
+ *
+ * Returns true if the shared secret was generated successfully, false
+ * if an error occurred. Both input and output parameters are with the
+ * LSB first.
+ */
+bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
+ u8 secret[32]);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 15/49] Bluetooth: Add basic support for sending our LE SC public key
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (13 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 14/49] Bluetooth: Add ECC library for LE Secure Connections Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 16/49] Bluetooth: Add handler function for receiving " Johan Hedberg
` (34 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
When the initial pairing request & response PDUs have been exchanged and
both have had the LE SC bit set the next step is to generate a ECDH
key pair and to send the public key to the remote side. This patch adds
basic support for generating the key pair and sending the public key
using the new Public Key SMP PDU. It is the initiating device that sends
the public key first and the non-initiating device responds by sending
its public key respectively (in a subsequent patch).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 4fed367da380..9317583751eb 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -29,10 +29,14 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>
+#include "ecc.h"
#include "smp.h"
#define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd)
+/* Keys which are not distributed with Secure Connections */
+#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);
+
#define SMP_TIMEOUT msecs_to_jiffies(30000)
#define AUTH_REQ_MASK(dev) (test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \
@@ -71,6 +75,10 @@ struct smp_chan {
struct smp_irk *remote_irk;
unsigned long flags;
+ /* Secure Connections variables */
+ u8 local_pk[64];
+ u8 local_sk[32];
+
struct crypto_blkcipher *tfm_aes;
struct crypto_hash *tfm_cmac;
};
@@ -1012,7 +1020,18 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+
+ clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
+
+ if (test_bit(SMP_FLAG_SC, &smp->flags)) {
+ SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
+ /* Clear bits which are generated but not distributed */
+ smp->remote_key_dist &= ~SMP_SC_NO_DIST;
+ /* Wait for Public Key from Initiating Device */
+ return 0;
+ } else {
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+ }
/* Request setup of TK */
ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
@@ -1022,6 +1041,23 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static u8 sc_send_public_key(struct smp_chan *smp)
+{
+ BT_DBG("");
+
+ /* Generate local key pair for Secure Connections */
+ if (!ecc_make_key(smp->local_pk, smp->local_sk))
+ return SMP_UNSPECIFIED;
+
+ BT_DBG("Local Public Key X: %32phN", smp->local_pk);
+ BT_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
+ BT_DBG("Local Private Key: %32phN", smp->local_sk);
+
+ smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
+
+ return 0;
+}
+
static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
@@ -1074,6 +1110,13 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
*/
smp->remote_key_dist &= rsp->resp_key_dist;
+ if (test_bit(SMP_FLAG_SC, &smp->flags)) {
+ /* Clear bits which are generated but not distributed */
+ smp->remote_key_dist &= ~SMP_SC_NO_DIST;
+ SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
+ return sc_send_public_key(smp);
+ }
+
auth |= req->auth_req;
ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 16/49] Bluetooth: Add handler function for receiving LE SC public key
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (14 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 15/49] Bluetooth: Add basic support for sending our LE SC public key Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 17/49] Bluetooth: Add support for sending LE SC Confirm value Johan Hedberg
` (33 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a handler function for the LE SC SMP Public Key PDU.
When we receive the key we proceed with generating the shared DHKey
value from the remote public key and local private key.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 9317583751eb..1cc438c9c2cb 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -50,6 +50,7 @@ enum {
SMP_FLAG_COMPLETE,
SMP_FLAG_INITIATOR,
SMP_FLAG_SC,
+ SMP_FLAG_REMOTE_PK,
};
struct smp_chan {
@@ -78,6 +79,8 @@ struct smp_chan {
/* Secure Connections variables */
u8 local_pk[64];
u8 local_sk[32];
+ u8 remote_pk[64];
+ u8 dhkey[32];
struct crypto_blkcipher *tfm_aes;
struct crypto_hash *tfm_cmac;
@@ -1513,6 +1516,43 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_public_key *key = (void *) skb->data;
+ struct hci_conn *hcon = conn->hcon;
+ struct l2cap_chan *chan = conn->smp;
+ struct smp_chan *smp = chan->data;
+ int err;
+
+ BT_DBG("conn %p", conn);
+
+ if (skb->len < sizeof(*key))
+ return SMP_INVALID_PARAMS;
+
+ memcpy(smp->remote_pk, key, 64);
+
+ /* Non-initiating device sends its public key after receiving
+ * the key from the initiating device.
+ */
+ if (!hcon->out) {
+ err = sc_send_public_key(smp);
+ if (err)
+ return err;
+ }
+
+ BT_DBG("Remote Public Key X: %32phN", smp->remote_pk);
+ BT_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
+
+ if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
+ return SMP_UNSPECIFIED;
+
+ BT_DBG("DHKey %32phN", smp->dhkey);
+
+ set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
+
+ return 0;
+}
+
static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
{
struct l2cap_conn *conn = chan->conn;
@@ -1597,6 +1637,10 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
reason = smp_cmd_sign_info(conn, skb);
break;
+ case SMP_CMD_PUBLIC_KEY:
+ reason = smp_cmd_public_key(conn, skb);
+ break;
+
default:
BT_DBG("Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 17/49] Bluetooth: Add support for sending LE SC Confirm value
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (15 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 16/49] Bluetooth: Add handler function for receiving " Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 18/49] Bluetooth: Add LE SC support for responding to Pairing Confirm PDU Johan Hedberg
` (32 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Once the public key exchange is complete the next step is for the
non-initiating device to send a SMP Pairing Confirm PDU to the
initiating device. This requires the use of a new smp_f4 confirm value
generation function which in turn builds on the AES-CMAC cryptographic
function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 1cc438c9c2cb..a1bfcb601c03 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -43,6 +43,9 @@
0x1f : 0x07)
#define KEY_DIST_MASK 0x07
+/* Maximum message length that can be passed to aes_cmac */
+#define CMAC_MSG_MAX 80
+
enum {
SMP_FLAG_TK_VALID,
SMP_FLAG_CFM_PENDING,
@@ -94,6 +97,84 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
dst[len - 1 - i] = src[i];
}
+static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
+ size_t len, u8 mac[16])
+{
+ uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX];
+ struct hash_desc desc;
+ struct scatterlist sg;
+ int err;
+
+ if (len > CMAC_MSG_MAX)
+ return -EFBIG;
+
+ if (!tfm) {
+ BT_ERR("tfm %p", tfm);
+ return -EINVAL;
+ }
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+
+ crypto_hash_init(&desc);
+
+ /* Swap key and message from LSB to MSB */
+ swap_buf(k, tmp, 16);
+ swap_buf(m, msg_msb, len);
+
+ BT_DBG("msg (len %zu) %*phN", len, len, m);
+ BT_DBG("key %16phN", k);
+
+ err = crypto_hash_setkey(tfm, tmp, 16);
+ if (err) {
+ BT_ERR("cipher setkey failed: %d", err);
+ return err;
+ }
+
+ sg_init_one(&sg, msg_msb, len);
+
+ err = crypto_hash_update(&desc, &sg, len);
+ if (err) {
+ BT_ERR("Hash update error %d", err);
+ return err;
+ }
+
+ err = crypto_hash_final(&desc, mac_msb);
+ if (err) {
+ BT_ERR("Hash final error %d", err);
+ return err;
+ }
+
+ swap_buf(mac_msb, mac, 16);
+
+ BT_DBG("mac %16phN", mac);
+
+ return 0;
+}
+
+static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
+ const u8 x[16], u8 z, u8 res[16])
+{
+ u8 m[65];
+ int err;
+
+ BT_DBG("u %32phN", u);
+ BT_DBG("v %32phN", v);
+ BT_DBG("x %16phN z %02x", x, z);
+
+ m[0] = z;
+ memcpy(m + 1, v, 32);
+ memcpy(m + 33, u, 32);
+
+ err = aes_cmac(tfm_cmac, x, m, sizeof(m), res);
+ if (err)
+ return err;
+
+ BT_DBG("res %16phN", res);
+
+ return err;
+}
+
static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
{
struct blkcipher_desc desc;
@@ -1522,6 +1603,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct smp_cmd_pairing_confirm cfm;
int err;
BT_DBG("conn %p", conn);
@@ -1550,6 +1632,20 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
+ /* The Initiating device waits for the non-initiating device to
+ * send the confirm value.
+ */
+ if (conn->hcon->out)
+ return 0;
+
+ err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
+ 0, cfm.confirm_val);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
+
return 0;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 18/49] Bluetooth: Add LE SC support for responding to Pairing Confirm PDU
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (16 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 17/49] Bluetooth: Add support for sending LE SC Confirm value Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 19/49] Bluetooth: Add support for LE SC numeric comparison Johan Hedberg
` (31 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
When LE SC is being used we should always respond to it by sending our
local random number. This patch adds a convenience function for it which
also contains a check for the pre-requisite public key exchange
completion
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a1bfcb601c03..36f3c75ac858 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1216,6 +1216,25 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static u8 sc_check_confirm(struct smp_chan *smp)
+{
+ struct l2cap_conn *conn = smp->conn;
+
+ BT_DBG("");
+
+ /* Public Key exchange must happen before any other steps */
+ if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
+ return SMP_UNSPECIFIED;
+
+ if (conn->hcon->out) {
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
+ smp->prnd);
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
+ }
+
+ return 0;
+}
+
static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_chan *chan = conn->smp;
@@ -1229,6 +1248,9 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
skb_pull(skb, sizeof(smp->pcnf));
+ if (test_bit(SMP_FLAG_SC, &smp->flags))
+ return sc_check_confirm(smp);
+
if (conn->hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 19/49] Bluetooth: Add support for LE SC numeric comparison
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (17 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 18/49] Bluetooth: Add LE SC support for responding to Pairing Confirm PDU Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 20/49] Bluetooth: Add support for handling LE SC user response Johan Hedberg
` (30 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
After the Pairing Confirm and Random PDUs have been exchanged in LE SC
it's time to generate a numeric comparison value using a new smp_g2
cryptographic function (which also builds on AES-CMAC). This patch adds
the smp_g2 implementation and updates the Pairing Random PDU handler to
proceed with the value genration and user confirmation.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 36f3c75ac858..00bafcae8814 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -175,6 +175,32 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
return err;
}
+static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
+ const u8 x[16], const u8 y[16], u32 *val)
+{
+ u8 m[80], tmp[16];
+ int err;
+
+ BT_DBG("u %32phN", u);
+ BT_DBG("v %32phN", v);
+ BT_DBG("x %16phN y %16phN", x, y);
+
+ memcpy(m, y, 16);
+ memcpy(m + 16, v, 32);
+ memcpy(m + 48, u, 32);
+
+ err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp);
+ if (err)
+ return err;
+
+ *val = get_unaligned_le32(tmp);
+ *val %= 1000000;
+
+ BT_DBG("val %06u", *val);
+
+ return 0;
+}
+
static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
{
struct blkcipher_desc desc;
@@ -1270,6 +1296,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_conn *hcon = conn->hcon;
+ u8 *pkax, *pkbx, *na, *nb;
+ u32 passkey;
+ int err;
BT_DBG("conn %p", conn);
@@ -1279,7 +1309,46 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd));
skb_pull(skb, sizeof(smp->rrnd));
- return smp_random(smp);
+ if (!test_bit(SMP_FLAG_SC, &smp->flags))
+ return smp_random(smp);
+
+ if (hcon->out) {
+ u8 cfm[16];
+
+ err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
+ smp->rrnd, 0, cfm);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ if (memcmp(smp->pcnf, cfm, 16))
+ return SMP_CONFIRM_FAILED;
+
+ pkax = smp->local_pk;
+ pkbx = smp->remote_pk;
+ na = smp->prnd;
+ nb = smp->rrnd;
+ } else {
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
+ smp->prnd);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+
+ pkax = smp->remote_pk;
+ pkbx = smp->local_pk;
+ na = smp->rrnd;
+ nb = smp->prnd;
+ }
+
+ err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
+ hcon->type, hcon->dst_type,
+ passkey, 0);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ return 0;
}
static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 20/49] Bluetooth: Add support for handling LE SC user response
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (18 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 19/49] Bluetooth: Add support for LE SC numeric comparison Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 21/49] Bluetooth: Add support for LE SC DHKey check PDU Johan Hedberg
` (29 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
With LE SC, once the user has responded to the numeric comparison it's
time to send DHKey check values in both directions. The DHKey check
value is generated using new smp_f5 and smp_f6 cryptographic functions.
The smp_f5 function is responsible for generating the LTK and the MacKey
values whereas the smp_f6 function takes the MacKey as input and
generates the DHKey Check value.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 00bafcae8814..bdbfbdba0089 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -84,6 +84,7 @@ struct smp_chan {
u8 local_sk[32];
u8 remote_pk[64];
u8 dhkey[32];
+ u8 mackey[16];
struct crypto_blkcipher *tfm_aes;
struct crypto_hash *tfm_cmac;
@@ -175,6 +176,86 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
return err;
}
+static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
+ u8 a1[7], u8 a2[7], u8 mackey[16], u8 ltk[16])
+{
+ /* The btle, salt and length "magic" values are as defined in
+ * the SMP section of the Bluetooth core specification. In ASCII
+ * the btle value ends up being 'btle'. The salt is just a
+ * random number whereas length is the value 256 in little
+ * endian format.
+ */
+ const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 };
+ const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
+ 0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c };
+ const u8 length[2] = { 0x00, 0x01 };
+ u8 m[53], t[16];
+ int err;
+
+ BT_DBG("w %32phN", w);
+ BT_DBG("n1 %16phN n2 %16phN", n1, n2);
+ BT_DBG("a1 %7phN a2 %7phN", a1, a2);
+
+ err = aes_cmac(tfm_cmac, salt, w, 32, t);
+ if (err)
+ return err;
+
+ BT_DBG("t %16phN", t);
+
+ memcpy(m, length, 2);
+ memcpy(m + 2, a2, 7);
+ memcpy(m + 9, a1, 7);
+ memcpy(m + 16, n2, 16);
+ memcpy(m + 32, n1, 16);
+ memcpy(m + 48, btle, 4);
+
+ m[52] = 0; /* Counter */
+
+ err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey);
+ if (err)
+ return err;
+
+ BT_DBG("mackey %16phN", mackey);
+
+ m[52] = 1; /* Counter */
+
+ err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk);
+ if (err)
+ return err;
+
+ BT_DBG("ltk %16phN", ltk);
+
+ return 0;
+}
+
+static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16],
+ const u8 n1[16], u8 n2[16], const u8 r[16],
+ const u8 io_cap[3], const u8 a1[7], const u8 a2[7],
+ u8 res[16])
+{
+ u8 m[65];
+ int err;
+
+ BT_DBG("w %16phN", w);
+ BT_DBG("n1 %16phN n2 %16phN", n1, n2);
+ BT_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
+
+ memcpy(m, a2, 7);
+ memcpy(m + 7, a1, 7);
+ memcpy(m + 14, io_cap, 3);
+ memcpy(m + 17, r, 16);
+ memcpy(m + 33, n2, 16);
+ memcpy(m + 49, n1, 16);
+
+ err = aes_cmac(tfm_cmac, w, m, sizeof(m), res);
+ if (err)
+ return err;
+
+ BT_DBG("res %16phN", res);
+
+ return err;
+}
+
static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
const u8 x[16], const u8 y[16], u32 *val)
{
@@ -1001,6 +1082,69 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
return smp;
}
+static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
+{
+ struct hci_conn *hcon = smp->conn->hcon;
+ u8 *na, *nb, a[7], b[7];
+
+ if (hcon->out) {
+ na = smp->prnd;
+ nb = smp->rrnd;
+ } else {
+ na = smp->rrnd;
+ nb = smp->prnd;
+ }
+
+ memcpy(a, &hcon->init_addr, 6);
+ memcpy(b, &hcon->resp_addr, 6);
+ a[6] = hcon->init_addr_type;
+ b[6] = hcon->resp_addr_type;
+
+ return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
+}
+
+static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
+{
+ struct hci_conn *hcon = smp->conn->hcon;
+ struct smp_cmd_dhkey_check check;
+ u8 a[7], b[7], *local_addr, *remote_addr;
+ u8 io_cap[3], r[16];
+
+ switch (mgmt_op) {
+ case MGMT_OP_USER_PASSKEY_NEG_REPLY:
+ smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
+ return 0;
+ case MGMT_OP_USER_CONFIRM_NEG_REPLY:
+ smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
+ return 0;
+ }
+
+ memcpy(a, &hcon->init_addr, 6);
+ memcpy(b, &hcon->resp_addr, 6);
+ a[6] = hcon->init_addr_type;
+ b[6] = hcon->resp_addr_type;
+
+ if (hcon->out) {
+ local_addr = a;
+ remote_addr = b;
+ memcpy(io_cap, &smp->preq[1], 3);
+ } else {
+ local_addr = b;
+ remote_addr = a;
+ memcpy(io_cap, &smp->prsp[1], 3);
+ }
+
+ memcpy(r, &passkey, sizeof(passkey));
+ memset(r + sizeof(passkey), 0, sizeof(r) - sizeof(passkey));
+
+ smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
+ local_addr, remote_addr, check.e);
+
+ smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
+
+ return 0;
+}
+
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1026,6 +1170,11 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
smp = chan->data;
+ if (test_bit(SMP_FLAG_SC, &smp->flags)) {
+ err = sc_user_reply(smp, mgmt_op, passkey);
+ goto unlock;
+ }
+
switch (mgmt_op) {
case MGMT_OP_USER_PASSKEY_REPLY:
value = le32_to_cpu(passkey);
@@ -1338,6 +1487,11 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
nb = smp->prnd;
}
+ /* Generate MacKey and LTK */
+ err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk);
+ if (err)
+ return SMP_UNSPECIFIED;
+
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
if (err)
return SMP_UNSPECIFIED;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 21/49] Bluetooth: Add support for LE SC DHKey check PDU
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (19 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 20/49] Bluetooth: Add support for handling LE SC user response Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 22/49] Bluetooth: Add support for LE SC key generation Johan Hedberg
` (28 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Once we receive the DHKey check PDU it's time to first verify that the
value is correct and then proceed with encrypting the link.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index bdbfbdba0089..a759105b252c 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1894,6 +1894,58 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ struct smp_cmd_dhkey_check *check = (void *) skb->data;
+ struct l2cap_chan *chan = conn->smp;
+ struct hci_conn *hcon = conn->hcon;
+ struct smp_chan *smp = chan->data;
+ u8 a[7], b[7], *local_addr, *remote_addr;
+ u8 io_cap[3], r[16], e[16];
+ int err;
+
+ BT_DBG("conn %p", conn);
+
+ if (skb->len < sizeof(*check))
+ return SMP_INVALID_PARAMS;
+
+ memcpy(a, &hcon->init_addr, 6);
+ memcpy(b, &hcon->resp_addr, 6);
+ a[6] = hcon->init_addr_type;
+ b[6] = hcon->resp_addr_type;
+
+ if (hcon->out) {
+ local_addr = a;
+ remote_addr = b;
+ memcpy(io_cap, &smp->prsp[1], 3);
+ } else {
+ local_addr = b;
+ remote_addr = a;
+ memcpy(io_cap, &smp->preq[1], 3);
+ }
+
+ memset(r, 0, sizeof(r));
+
+ err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
+ io_cap, remote_addr, local_addr, e);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ if (memcmp(check->e, e, 16))
+ return SMP_DHKEY_CHECK_FAILED;
+
+ smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
+ SMP_LTK_P256, 0, smp->tk, smp->enc_key_size,
+ 0, 0);
+
+ if (hcon->out) {
+ hci_le_start_enc(hcon, 0, 0, smp->tk);
+ hcon->enc_key_size = smp->enc_key_size;
+ }
+
+ return 0;
+}
+
static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
{
struct l2cap_conn *conn = chan->conn;
@@ -1982,6 +2034,10 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
reason = smp_cmd_public_key(conn, skb);
break;
+ case SMP_CMD_DHKEY_CHECK:
+ reason = smp_cmd_dhkey_check(conn, skb);
+ break;
+
default:
BT_DBG("Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 22/49] Bluetooth: Add support for LE SC key generation
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (20 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 21/49] Bluetooth: Add support for LE SC DHKey check PDU Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 23/49] Bluetooth: Track authentication method in SMP context Johan Hedberg
` (27 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
As the last step of the LE SC pairing process it's time to generate and
distribute keys. The generation part is unique to LE SC and so this
patch adds a dedicated function for it. We also clear the distribution
bits for keys which are not distributed with LE SC, so that the code
shared with legacy SMP will not go ahead and try to distribute them.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a759105b252c..816cbb63b68b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -77,6 +77,7 @@ struct smp_chan {
struct smp_ltk *ltk;
struct smp_ltk *slave_ltk;
struct smp_irk *remote_irk;
+ u8 *link_key;
unsigned long flags;
/* Secure Connections variables */
@@ -321,6 +322,22 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
return err;
}
+static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
+ const u8 key_id[4], u8 res[16])
+{
+ int err;
+
+ BT_DBG("w %16phN key_id %4phN", w, key_id);
+
+ err = aes_cmac(tfm_cmac, w, key_id, 4, res);
+ if (err)
+ return err;
+
+ BT_DBG("res %16phN", res);
+
+ return err;
+}
+
static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
{
u8 _res[16];
@@ -594,6 +611,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
kfree(smp->csrk);
kfree(smp->slave_csrk);
+ kfree(smp->link_key);
crypto_free_blkcipher(smp->tfm_aes);
crypto_free_hash(smp->tfm_cmac);
@@ -907,6 +925,37 @@ static void smp_notify_keys(struct l2cap_conn *conn)
bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
}
+
+ if (smp->link_key) {
+ hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
+ smp->link_key, HCI_LK_AUTH_COMBINATION_P256,
+ 0, NULL);
+ }
+}
+
+static void sc_generate_link_key(struct smp_chan *smp)
+{
+ /* These constants are as specified in the core specification.
+ * In ASCII they spell out to 'tmp1' and 'lebr'.
+ */
+ const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+ const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
+
+ smp->link_key = kzalloc(16, GFP_KERNEL);
+ if (!smp->link_key)
+ return;
+
+ if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
+ kfree(smp->link_key);
+ smp->link_key = NULL;
+ return;
+ }
+
+ if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
+ kfree(smp->link_key);
+ smp->link_key = NULL;
+ return;
+ }
}
static void smp_allow_key_dist(struct smp_chan *smp)
@@ -951,6 +1000,14 @@ static void smp_distribute_keys(struct smp_chan *smp)
*keydist &= req->resp_key_dist;
}
+ if (test_bit(SMP_FLAG_SC, &smp->flags)) {
+ if (*keydist & SMP_DIST_LINK_KEY)
+ sc_generate_link_key(smp);
+
+ /* Clear the keys which are generated but not distributed */
+ *keydist &= ~SMP_SC_NO_DIST;
+ }
+
BT_DBG("keydist 0x%x", *keydist);
if (*keydist & SMP_DIST_ENC_KEY) {
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 23/49] Bluetooth: Track authentication method in SMP context
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (21 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 22/49] Bluetooth: Add support for LE SC key generation Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 24/49] Bluetooth: Add selection of the SC authentication method Johan Hedberg
` (26 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
For Secure Connections we'll select the authentication method as soon as
we receive the public key, but only use it later (both when actually
triggering the method as well as when determining the quality of the
resulting LTK). Store the method therefore in the SMP context.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 816cbb63b68b..651963f26da0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -79,6 +79,7 @@ struct smp_chan {
struct smp_irk *remote_irk;
u8 *link_key;
unsigned long flags;
+ u8 method;
/* Secure Connections variables */
u8 local_pk[64];
@@ -688,7 +689,6 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- u8 method;
u32 passkey = 0;
int ret = 0;
@@ -705,26 +705,28 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
* table.
*/
if (!(auth & SMP_AUTH_MITM))
- method = JUST_CFM;
+ smp->method = JUST_CFM;
else
- method = get_auth_method(smp, local_io, remote_io);
+ smp->method = get_auth_method(smp, local_io, remote_io);
/* Don't confirm locally initiated pairing attempts */
- if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
- method = JUST_WORKS;
+ if (smp->method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR,
+ &smp->flags))
+ smp->method = JUST_WORKS;
/* Don't bother user space with no IO capabilities */
- if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
- method = JUST_WORKS;
+ if (smp->method == JUST_CFM &&
+ hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
+ smp->method = JUST_WORKS;
/* If Just Works, Continue with Zero TK */
- if (method == JUST_WORKS) {
+ if (smp->method == JUST_WORKS) {
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
return 0;
}
/* Not Just Works/Confirm results in MITM Authentication */
- if (method != JUST_CFM) {
+ if (smp->method != JUST_CFM) {
set_bit(SMP_FLAG_MITM_AUTH, &smp->flags);
if (hcon->pending_sec_level < BT_SECURITY_HIGH)
hcon->pending_sec_level = BT_SECURITY_HIGH;
@@ -733,15 +735,15 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
/* If both devices have Keyoard-Display I/O, the master
* Confirms and the slave Enters the passkey.
*/
- if (method == OVERLAP) {
+ if (smp->method == OVERLAP) {
if (hcon->role == HCI_ROLE_MASTER)
- method = CFM_PASSKEY;
+ smp->method = CFM_PASSKEY;
else
- method = REQ_PASSKEY;
+ smp->method = REQ_PASSKEY;
}
/* Generate random passkey. */
- if (method == CFM_PASSKEY) {
+ if (smp->method == CFM_PASSKEY) {
memset(smp->tk, 0, sizeof(smp->tk));
get_random_bytes(&passkey, sizeof(passkey));
passkey %= 1000000;
@@ -750,10 +752,10 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
}
- if (method == REQ_PASSKEY)
+ if (smp->method == REQ_PASSKEY)
ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type);
- else if (method == JUST_CFM)
+ else if (smp->method == JUST_CFM)
ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type,
passkey, 1);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 24/49] Bluetooth: Add selection of the SC authentication method
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (22 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 23/49] Bluetooth: Track authentication method in SMP context Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 25/49] Bluetooth: Detect SMP SC debug keys Johan Hedberg
` (25 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds code to select the authentication method for Secure
Connections based on the local and remote capabilities. A new
DSP_PASSKEY method is also added for displaying the passkey - something
that is not part of legacy SMP pairing.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 69 insertions(+), 5 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 651963f26da0..8753d8120850 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -661,6 +661,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason)
#define REQ_PASSKEY 0x02
#define CFM_PASSKEY 0x03
#define REQ_OOB 0x04
+#define DSP_PASSKEY 0x05
#define OVERLAP 0xFF
static const u8 gen_method[5][5] = {
@@ -671,6 +672,14 @@ static const u8 gen_method[5][5] = {
{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
};
+static const u8 sc_method[5][5] = {
+ { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
+ { JUST_WORKS, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
+ { DSP_PASSKEY, DSP_PASSKEY, REQ_PASSKEY, JUST_WORKS, DSP_PASSKEY },
+ { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
+ { DSP_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
+};
+
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
{
/* If either side has unknown io_caps, use JUST_CFM (which gets
@@ -680,6 +689,9 @@ static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
remote_io > SMP_IO_KEYBOARD_DISPLAY)
return JUST_CFM;
+ if (test_bit(SMP_FLAG_SC, &smp->flags))
+ return sc_method[remote_io][local_io];
+
return gen_method[remote_io][local_io];
}
@@ -1305,6 +1317,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&smp->preq[1], req, sizeof(*req));
skb_pull(skb, sizeof(*req));
+ build_pairing_cmd(conn, req, &rsp, auth);
+
+ if (rsp.auth_req & SMP_AUTH_SC)
+ set_bit(SMP_FLAG_SC, &smp->flags);
+
if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
else
@@ -1323,11 +1340,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return SMP_AUTH_REQUIREMENTS;
}
- build_pairing_cmd(conn, req, &rsp, auth);
-
- if (rsp.auth_req & SMP_AUTH_SC)
- set_bit(SMP_FLAG_SC, &smp->flags);
-
key_size = min(req->max_key_size, rsp.max_key_size);
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
@@ -1901,12 +1913,54 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static u8 sc_select_method(struct smp_chan *smp)
+{
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_conn *hcon = conn->hcon;
+ struct smp_cmd_pairing *local, *remote;
+ u8 local_mitm, remote_mitm, local_io, remote_io, method;
+
+ /* The preq/prsp contain the raw Pairing Request/Response PDUs
+ * which are needed as inputs to some crypto functions. To get
+ * the "struct smp_cmd_pairing" from them we need to skip the
+ * first byte which contains the opcode.
+ */
+ if (hcon->out) {
+ local = (void *) &smp->preq[1];
+ remote = (void *) &smp->prsp[1];
+ } else {
+ local = (void *) &smp->prsp[1];
+ remote = (void *) &smp->preq[1];
+ }
+
+ local_io = local->io_capability;
+ remote_io = remote->io_capability;
+
+ local_mitm = (local->auth_req & SMP_AUTH_MITM);
+ remote_mitm = (remote->auth_req & SMP_AUTH_MITM);
+
+ /* If either side wants MITM, look up the method from the table,
+ * otherwise use JUST WORKS.
+ */
+ if (local_mitm || remote_mitm)
+ method = get_auth_method(smp, local_io, remote_io);
+ else
+ method = JUST_WORKS;
+
+ /* Don't confirm locally initiated pairing attempts */
+ if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
+ method = JUST_WORKS;
+
+ return method;
+}
+
static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_public_key *key = (void *) skb->data;
struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_dev *hdev = hcon->hdev;
struct smp_cmd_pairing_confirm cfm;
int err;
@@ -1936,6 +1990,16 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
+ smp->method = sc_select_method(smp);
+
+ BT_DBG("%s selected method 0x%02x", hdev->name, smp->method);
+
+ /* JUST_WORKS and JUST_CFM result in an unauthenticated key */
+ if (smp->method == JUST_WORKS || smp->method == JUST_CFM)
+ hcon->pending_sec_level = BT_SECURITY_MEDIUM;
+ else
+ hcon->pending_sec_level = BT_SECURITY_FIPS;
+
/* The Initiating device waits for the non-initiating device to
* send the confirm value.
*/
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 25/49] Bluetooth: Detect SMP SC debug keys
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (23 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 24/49] Bluetooth: Add selection of the SC authentication method Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 26/49] Bluetooth: Add check for accidentally generating a debug key Johan Hedberg
` (24 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
We need to be able to detect if the remote side used a debug key for the
pairing. This patch adds the debug key defines and sets a flag to
indicate that a debug key was used. The debug private key (debug_sk) is
also added in this patch but will only be used in a subsequent patch
when local debug key support is implemented.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8753d8120850..74b0489fea4f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -54,6 +54,7 @@ enum {
SMP_FLAG_INITIATOR,
SMP_FLAG_SC,
SMP_FLAG_REMOTE_PK,
+ SMP_FLAG_DEBUG_KEY,
};
struct smp_chan {
@@ -92,6 +93,29 @@ struct smp_chan {
struct crypto_hash *tfm_cmac;
};
+/* These debug key values are defined in the SMP section of the core
+ * specification. debug_pk is the public debug key and debug_sk the
+ * private debug key.
+ */
+static const u8 debug_pk[64] = {
+ 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
+ 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
+ 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+ 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
+
+ 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
+ 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
+ 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
+ 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
+};
+
+static const u8 debug_sk[32] = {
+ 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
+ 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
+ 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
+ 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
+};
+
static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
{
size_t i;
@@ -2000,6 +2024,9 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
else
hcon->pending_sec_level = BT_SECURITY_FIPS;
+ if (!memcmp(debug_pk, smp->remote_pk, 64))
+ set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
+
/* The Initiating device waits for the non-initiating device to
* send the confirm value.
*/
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 26/49] Bluetooth: Add check for accidentally generating a debug key
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (24 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 25/49] Bluetooth: Detect SMP SC debug keys Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 27/49] Bluetooth: Set correct LTK type and authentication for SC Johan Hedberg
` (23 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
It is very unlikely, but to have a 100% guarantee of the generated key
type we need to reject any keys which happen to match the debug key.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 74b0489fea4f..13fbe05d33cb 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1399,9 +1399,17 @@ static u8 sc_send_public_key(struct smp_chan *smp)
{
BT_DBG("");
- /* Generate local key pair for Secure Connections */
- if (!ecc_make_key(smp->local_pk, smp->local_sk))
- return SMP_UNSPECIFIED;
+ while (true) {
+ /* Generate local key pair for Secure Connections */
+ if (!ecc_make_key(smp->local_pk, smp->local_sk))
+ return SMP_UNSPECIFIED;
+
+ /* This is unlikely, but we need to check that we didn't
+ * accidentially generate a debug key.
+ */
+ if (memcmp(smp->local_sk, debug_sk, 32))
+ break;
+ }
BT_DBG("Local Public Key X: %32phN", smp->local_pk);
BT_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 27/49] Bluetooth: Set correct LTK type and authentication for SC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (25 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 26/49] Bluetooth: Add check for accidentally generating a debug key Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 28/49] Bluetooth: Add support for SC just-works pairing Johan Hedberg
` (22 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
After generating the LTK we should set the correct type (normal SC or
debug) and authentication information for it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 13fbe05d33cb..8c7862044e44 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2060,6 +2060,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_chan *smp = chan->data;
u8 a[7], b[7], *local_addr, *remote_addr;
u8 io_cap[3], r[16], e[16];
+ u8 key_type, auth;
int err;
BT_DBG("conn %p", conn);
@@ -2092,8 +2093,18 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
if (memcmp(check->e, e, 16))
return SMP_DHKEY_CHECK_FAILED;
+ if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
+ key_type = SMP_LTK_P256_DEBUG;
+ else
+ key_type = SMP_LTK_P256;
+
+ if (hcon->pending_sec_level == BT_SECURITY_FIPS)
+ auth = 1;
+ else
+ auth = 0;
+
smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
- SMP_LTK_P256, 0, smp->tk, smp->enc_key_size,
+ key_type, auth, smp->tk, smp->enc_key_size,
0, 0);
if (hcon->out) {
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 28/49] Bluetooth: Add support for SC just-works pairing
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (26 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 27/49] Bluetooth: Set correct LTK type and authentication for SC Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 29/49] Bluetooth: Fix BR/EDR Link Key type when derived through LE SC Johan Hedberg
` (21 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
If the just-works method was chosen we shouldn't send anything to user
space but simply proceed with sending the DHKey Check PDU. This patch
adds the necessary code for it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 39 +++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8c7862044e44..7fdeca7edb7c 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1198,22 +1198,13 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
}
-static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
+static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
{
struct hci_conn *hcon = smp->conn->hcon;
struct smp_cmd_dhkey_check check;
u8 a[7], b[7], *local_addr, *remote_addr;
u8 io_cap[3], r[16];
- switch (mgmt_op) {
- case MGMT_OP_USER_PASSKEY_NEG_REPLY:
- smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
- return 0;
- case MGMT_OP_USER_CONFIRM_NEG_REPLY:
- smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
- return 0;
- }
-
memcpy(a, &hcon->init_addr, 6);
memcpy(b, &hcon->resp_addr, 6);
a[6] = hcon->init_addr_type;
@@ -1229,13 +1220,29 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
memcpy(io_cap, &smp->prsp[1], 3);
}
- memcpy(r, &passkey, sizeof(passkey));
- memset(r + sizeof(passkey), 0, sizeof(r) - sizeof(passkey));
+ memset(r, 0, sizeof(r));
+
+ if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
+ memcpy(r, &passkey, sizeof(passkey));
smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
local_addr, remote_addr, check.e);
smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
+}
+
+static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
+{
+ switch (mgmt_op) {
+ case MGMT_OP_USER_PASSKEY_NEG_REPLY:
+ smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
+ return 0;
+ case MGMT_OP_USER_CONFIRM_NEG_REPLY:
+ smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
+ return 0;
+ }
+
+ sc_dhkey_check(smp, passkey);
return 0;
}
@@ -1599,6 +1606,14 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (err)
return SMP_UNSPECIFIED;
+ if (smp->method == JUST_WORKS) {
+ if (hcon->out) {
+ sc_dhkey_check(smp, passkey);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+ }
+ return 0;
+ }
+
err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type,
passkey, 0);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 29/49] Bluetooth: Fix BR/EDR Link Key type when derived through LE SC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (27 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 28/49] Bluetooth: Add support for SC just-works pairing Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 30/49] Bluetooth: Add passkey entry support for " Johan Hedberg
` (20 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
We need to set the correct Link Key type based on the properties of the
LE SC pairing that it was derived from. If debug keys were used the type
should be a debug key, and the authenticated vs unauthenticated
information should be set on what kind of security level was reached.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/hci_core.c | 4 ++++
net/bluetooth/smp.c | 27 ++++++++++++++++++++++++---
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6c3220e9484f..2fa9f2b2bee3 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3160,6 +3160,10 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
if (!conn)
return true;
+ /* BR/EDR key derived using SC from an LE link */
+ if (conn->type == LE_LINK)
+ return true;
+
/* Neither local nor remote side had no-bonding as requirement */
if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
return true;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7fdeca7edb7c..861d2cf3ccc9 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -965,9 +965,30 @@ static void smp_notify_keys(struct l2cap_conn *conn)
}
if (smp->link_key) {
- hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
- smp->link_key, HCI_LK_AUTH_COMBINATION_P256,
- 0, NULL);
+ struct link_key *key;
+ u8 type;
+
+ if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
+ type = HCI_LK_DEBUG_COMBINATION;
+ else if (hcon->sec_level == BT_SECURITY_FIPS)
+ type = HCI_LK_AUTH_COMBINATION_P256;
+ else
+ type = HCI_LK_UNAUTH_COMBINATION_P256;
+
+ key = hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
+ smp->link_key, type, 0, &persistent);
+ if (key) {
+ mgmt_new_link_key(hdev, key, persistent);
+
+ /* Don't keep debug keys around if the relevant
+ * flag is not set.
+ */
+ if (!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags) &&
+ key->type == HCI_LK_DEBUG_COMBINATION) {
+ list_del_rcu(&key->list);
+ kfree_rcu(key, rcu);
+ }
+ }
}
}
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 30/49] Bluetooth: Add passkey entry support for LE SC
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (28 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 29/49] Bluetooth: Fix BR/EDR Link Key type when derived through LE SC Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 31/49] Bluetooth: Fix DHKey Check sending order for slave role Johan Hedberg
` (19 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The passkey entry mechanism involves either both sides requesting the
user for a passkey, or one side requesting the passkey while the other
one displays it. The behavior as far as SMP PDUs are concerned are
considerably different from numeric comparison and therefore requires
several new functions to handle it.
In essence passkey entry involves both sides gradually committing to
each bit of the passkey which involves 20 rounds of pairing confirm and
pairing random PDUS being sent in both directions.
This patch adds a new smp->passkey_round variable to track the current
round of the passkey commitment and reuses the variables already present
in struct hci_conn for the passkey and entered key count.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 180 insertions(+), 11 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 861d2cf3ccc9..7a9b491ffa1a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -55,6 +55,7 @@ enum {
SMP_FLAG_SC,
SMP_FLAG_REMOTE_PK,
SMP_FLAG_DEBUG_KEY,
+ SMP_FLAG_WAIT_USER,
};
struct smp_chan {
@@ -81,6 +82,7 @@ struct smp_chan {
u8 *link_key;
unsigned long flags;
u8 method;
+ u8 passkey_round;
/* Secure Connections variables */
u8 local_pk[64];
@@ -1219,7 +1221,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
}
-static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
+static void sc_dhkey_check(struct smp_chan *smp)
{
struct hci_conn *hcon = smp->conn->hcon;
struct smp_cmd_dhkey_check check;
@@ -1244,7 +1246,7 @@ static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
memset(r, 0, sizeof(r));
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
- memcpy(r, &passkey, sizeof(passkey));
+ put_unaligned_le32(hcon->passkey_notify, r);
smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
local_addr, remote_addr, check.e);
@@ -1252,8 +1254,124 @@ static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
}
+static u8 sc_passkey_send_confirm(struct smp_chan *smp)
+{
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_conn *hcon = conn->hcon;
+ struct smp_cmd_pairing_confirm cfm;
+ u8 r;
+
+ r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
+ r |= 0x80;
+
+ get_random_bytes(smp->prnd, sizeof(smp->prnd));
+
+ if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r,
+ cfm.confirm_val))
+ return SMP_UNSPECIFIED;
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
+
+ return 0;
+}
+
+static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
+{
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_conn *hcon = conn->hcon;
+ struct hci_dev *hdev = hcon->hdev;
+ u8 cfm[16], r;
+
+ /* Ignore the PDU if we've already done 20 rounds (0 - 19) */
+ if (smp->passkey_round >= 20)
+ return 0;
+
+ switch (smp_op) {
+ case SMP_CMD_PAIRING_RANDOM:
+ r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
+ r |= 0x80;
+
+ if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
+ smp->rrnd, r, cfm))
+ return SMP_UNSPECIFIED;
+
+ if (memcmp(smp->pcnf, cfm, 16))
+ return SMP_CONFIRM_FAILED;
+
+ smp->passkey_round++;
+
+ if (smp->passkey_round == 20) {
+ /* Generate MacKey and LTK */
+ if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk))
+ return SMP_UNSPECIFIED;
+ }
+
+ /* The round is only complete when the initiator
+ * receives pairing random.
+ */
+ if (!hcon->out) {
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
+ sizeof(smp->prnd), smp->prnd);
+ if (smp->passkey_round == 20) {
+ sc_dhkey_check(smp);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+ } else {
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+ }
+ return 0;
+ }
+
+ /* Start the next round */
+ if (smp->passkey_round != 20)
+ return sc_passkey_round(smp, 0);
+
+ /* Passkey rounds are complete - start DHKey Check */
+ sc_dhkey_check(smp);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+
+ break;
+
+ case SMP_CMD_PAIRING_CONFIRM:
+ if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
+ set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
+ return 0;
+ }
+
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
+
+ if (hcon->out) {
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
+ sizeof(smp->prnd), smp->prnd);
+ return 0;
+ }
+
+ return sc_passkey_send_confirm(smp);
+
+ case SMP_CMD_PUBLIC_KEY:
+ default:
+ /* Initiating device starts the round */
+ if (!hcon->out)
+ return 0;
+
+ BT_DBG("%s Starting passkey round %u", hdev->name,
+ smp->passkey_round + 1);
+
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+
+ return sc_passkey_send_confirm(smp);
+ }
+
+ return 0;
+}
+
static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
{
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_conn *hcon = conn->hcon;
+ u8 smp_op;
+
+ clear_bit(SMP_FLAG_WAIT_USER, &smp->flags);
+
switch (mgmt_op) {
case MGMT_OP_USER_PASSKEY_NEG_REPLY:
smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
@@ -1261,9 +1379,22 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
case MGMT_OP_USER_CONFIRM_NEG_REPLY:
smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
return 0;
+ case MGMT_OP_USER_PASSKEY_REPLY:
+ hcon->passkey_notify = le32_to_cpu(passkey);
+ smp->passkey_round = 0;
+
+ if (test_and_clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags))
+ smp_op = SMP_CMD_PAIRING_CONFIRM;
+ else
+ smp_op = 0;
+
+ if (sc_passkey_round(smp, smp_op))
+ return -EIO;
+
+ return 0;
}
- sc_dhkey_check(smp, passkey);
+ sc_dhkey_check(smp);
return 0;
}
@@ -1532,6 +1663,9 @@ static u8 sc_check_confirm(struct smp_chan *smp)
if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
return SMP_UNSPECIFIED;
+ if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
+ return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
+
if (conn->hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
@@ -1592,6 +1726,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (!test_bit(SMP_FLAG_SC, &smp->flags))
return smp_random(smp);
+ /* Passkey entry has special treatment */
+ if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
+ return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
+
if (hcon->out) {
u8 cfm[16];
@@ -1623,24 +1761,25 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (err)
return SMP_UNSPECIFIED;
- err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
- if (err)
- return SMP_UNSPECIFIED;
-
if (smp->method == JUST_WORKS) {
if (hcon->out) {
- sc_dhkey_check(smp, passkey);
+ sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
}
return 0;
}
- err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
- hcon->type, hcon->dst_type,
- passkey, 0);
+ err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type,
+ hcon->dst_type, passkey, 0);
if (err)
return SMP_UNSPECIFIED;
+ set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
+
return 0;
}
@@ -2071,6 +2210,33 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
if (!memcmp(debug_pk, smp->remote_pk, 64))
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
+ if (smp->method == DSP_PASSKEY) {
+ get_random_bytes(&hcon->passkey_notify,
+ sizeof(hcon->passkey_notify));
+ hcon->passkey_notify %= 1000000;
+ hcon->passkey_entered = 0;
+ smp->passkey_round = 0;
+ if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type,
+ hcon->dst_type,
+ hcon->passkey_notify,
+ hcon->passkey_entered))
+ return SMP_UNSPECIFIED;
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+ return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
+ }
+
+ if (hcon->out)
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+
+ if (smp->method == REQ_PASSKEY) {
+ if (mgmt_user_passkey_request(hdev, &hcon->dst, hcon->type,
+ hcon->dst_type))
+ return SMP_UNSPECIFIED;
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+ set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
+ return 0;
+ }
+
/* The Initiating device waits for the non-initiating device to
* send the confirm value.
*/
@@ -2121,6 +2287,9 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
memset(r, 0, sizeof(r));
+ if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
+ put_unaligned_le32(hcon->passkey_notify, r);
+
err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
io_cap, remote_addr, local_addr, e);
if (err)
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 31/49] Bluetooth: Fix DHKey Check sending order for slave role
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (29 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 30/49] Bluetooth: Add passkey entry support for " Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 32/49] Bluetooth: Add dummy handler for LE SC keypress notification Johan Hedberg
` (18 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
According to the LE SC specification the initiating device sends its
DHKey check first and the non-initiating devices sends its DHKey check
as a response to this. It's also important that the non-initiating
device doesn't send the response if it's still waiting for user input.
In order to synchronize all this a new flag is added.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 60 ++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 43 insertions(+), 17 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7a9b491ffa1a..458d07d5603b 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -56,6 +56,7 @@ enum {
SMP_FLAG_REMOTE_PK,
SMP_FLAG_DEBUG_KEY,
SMP_FLAG_WAIT_USER,
+ SMP_FLAG_DHKEY_PENDING,
};
struct smp_chan {
@@ -994,6 +995,29 @@ static void smp_notify_keys(struct l2cap_conn *conn)
}
}
+static void sc_add_ltk(struct smp_chan *smp)
+{
+ struct hci_conn *hcon = smp->conn->hcon;
+ u8 key_type, auth;
+
+ if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
+ key_type = SMP_LTK_P256_DEBUG;
+ else
+ key_type = SMP_LTK_P256;
+
+ if (hcon->pending_sec_level == BT_SECURITY_FIPS)
+ auth = 1;
+ else
+ auth = 0;
+
+ memset(smp->tk + smp->enc_key_size, 0,
+ SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
+
+ smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
+ key_type, auth, smp->tk, smp->enc_key_size,
+ 0, 0);
+}
+
static void sc_generate_link_key(struct smp_chan *smp)
{
/* These constants are as specified in the core specification.
@@ -1312,12 +1336,10 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
if (!hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
sizeof(smp->prnd), smp->prnd);
- if (smp->passkey_round == 20) {
- sc_dhkey_check(smp);
+ if (smp->passkey_round == 20)
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- } else {
+ else
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
- }
return 0;
}
@@ -1394,7 +1416,14 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
return 0;
}
- sc_dhkey_check(smp);
+ /* Initiator sends DHKey check first */
+ if (hcon->out) {
+ sc_dhkey_check(smp);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+ } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
+ sc_dhkey_check(smp);
+ sc_add_ltk(smp);
+ }
return 0;
}
@@ -2262,7 +2291,6 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_chan *smp = chan->data;
u8 a[7], b[7], *local_addr, *remote_addr;
u8 io_cap[3], r[16], e[16];
- u8 key_type, auth;
int err;
BT_DBG("conn %p", conn);
@@ -2298,19 +2326,17 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
if (memcmp(check->e, e, 16))
return SMP_DHKEY_CHECK_FAILED;
- if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
- key_type = SMP_LTK_P256_DEBUG;
- else
- key_type = SMP_LTK_P256;
+ if (!hcon->out) {
+ if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
+ set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
+ return 0;
+ }
- if (hcon->pending_sec_level == BT_SECURITY_FIPS)
- auth = 1;
- else
- auth = 0;
+ /* Slave sends DHKey check as response to master */
+ sc_dhkey_check(smp);
+ }
- smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
- key_type, auth, smp->tk, smp->enc_key_size,
- 0, 0);
+ sc_add_ltk(smp);
if (hcon->out) {
hci_le_start_enc(hcon, 0, 0, smp->tk);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 32/49] Bluetooth: Add dummy handler for LE SC keypress notification
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (30 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 31/49] Bluetooth: Fix DHKey Check sending order for slave role Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 33/49] Bluetooth: Use debug keys for SMP when HCI_USE_DEBUG_KEYS is set Johan Hedberg
` (17 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Since we don not actively try to clear the keypress notification bit we
might get these PDUs. To avoid failing the pairing process add a simple
dummy handler for these for now.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 458d07d5603b..16bd15e04b85 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2346,6 +2346,16 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
+static int smp_cmd_keypress_notify(struct l2cap_conn *conn,
+ struct sk_buff *skb)
+{
+ struct smp_cmd_keypress_notify *kp = (void *) skb->data;
+
+ BT_DBG("value 0x%02x", kp->value);
+
+ return 0;
+}
+
static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
{
struct l2cap_conn *conn = chan->conn;
@@ -2438,6 +2448,10 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
reason = smp_cmd_dhkey_check(conn, skb);
break;
+ case SMP_CMD_KEYPRESS_NOTIFY:
+ reason = smp_cmd_keypress_notify(conn, skb);
+ break;
+
default:
BT_DBG("Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 33/49] Bluetooth: Use debug keys for SMP when HCI_USE_DEBUG_KEYS is set
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (31 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 32/49] Bluetooth: Add dummy handler for LE SC keypress notification Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 34/49] Bluetooth: Add hci_conn flag for new link key generation Johan Hedberg
` (16 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The HCI_USE_DEBUG_KEYS flag is intended to force our side to always use
debug keys for pairing. This means both BR/EDR SSP as well as SMP with
LE Secure Connections. This patch updates the SMP code to use the debug
keys instead of generating a random local key pair when the flag is set.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 16bd15e04b85..3aad5864a5e1 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1585,18 +1585,27 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
static u8 sc_send_public_key(struct smp_chan *smp)
{
+ struct hci_dev *hdev = smp->conn->hcon->hdev;
+
BT_DBG("");
- while (true) {
- /* Generate local key pair for Secure Connections */
- if (!ecc_make_key(smp->local_pk, smp->local_sk))
- return SMP_UNSPECIFIED;
+ if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) {
+ BT_DBG("Using debug keys");
+ memcpy(smp->local_pk, debug_pk, 64);
+ memcpy(smp->local_sk, debug_sk, 32);
+ set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
+ } else {
+ while (true) {
+ /* Generate local key pair for Secure Connections */
+ if (!ecc_make_key(smp->local_pk, smp->local_sk))
+ return SMP_UNSPECIFIED;
- /* This is unlikely, but we need to check that we didn't
- * accidentially generate a debug key.
- */
- if (memcmp(smp->local_sk, debug_sk, 32))
- break;
+ /* This is unlikely, but we need to check that
+ * we didn't accidentially generate a debug key.
+ */
+ if (memcmp(smp->local_sk, debug_sk, 32))
+ break;
+ }
}
BT_DBG("Local Public Key X: %32phN", smp->local_pk);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 34/49] Bluetooth: Add hci_conn flag for new link key generation
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (32 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 33/49] Bluetooth: Use debug keys for SMP when HCI_USE_DEBUG_KEYS is set Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 35/49] Bluetooth: Add debugfs switch for forcing SMP over BR/EDR Johan Hedberg
` (15 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
For LE Secure Connections we want to trigger cross transport key
generation only if a new link key was actually created during the BR/EDR
connection. This patch adds a new flag to track this information.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_event.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 90929641d0f0..42f9362a83c1 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -559,6 +559,7 @@ enum {
HCI_CONN_AUTH_INITIATOR,
HCI_CONN_DROP,
HCI_CONN_PARAM_REMOVAL_PEND,
+ HCI_CONN_NEW_LINK_KEY,
};
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 34ecbf0b7e5b..c3d6390e3b7b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3249,6 +3249,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
+ clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
+
if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
@@ -3301,6 +3303,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
hci_conn_drop(conn);
+ set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
conn_set_key(conn, ev->key_type, conn->pin_length);
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 35/49] Bluetooth: Add debugfs switch for forcing SMP over BR/EDR
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (33 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 34/49] Bluetooth: Add hci_conn flag for new link key generation Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 36/49] Bluetooth: Add skeleton for BR/EDR SMP channel Johan Hedberg
` (14 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
To make it possible to use LE SC functionality over BR/EDR with pre-4.1
controllers (that do not support BR/EDR SC links) it's useful to be able
to force LE SC operations even over a traditional SSP protected link.
This patch adds a debugfs switch to force a special debug flag which is
used to skip the checks for BR/EDR SC support.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/hci_core.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e56f9099f8e3..569c077778b6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -163,6 +163,7 @@ enum {
enum {
HCI_DUT_MODE,
HCI_FORCE_SC,
+ HCI_FORCE_LESC,
HCI_FORCE_STATIC_ADDR,
};
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2fa9f2b2bee3..581e13e9dc32 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -406,6 +406,49 @@ static const struct file_operations force_sc_support_fops = {
.llseek = default_llseek,
};
+static ssize_t force_lesc_support_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct hci_dev *hdev = file->private_data;
+ char buf[3];
+
+ buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N';
+ buf[1] = '\n';
+ buf[2] = '\0';
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t force_lesc_support_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct hci_dev *hdev = file->private_data;
+ char buf[32];
+ size_t buf_size = min(count, (sizeof(buf)-1));
+ bool enable;
+
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+ if (strtobool(buf, &enable))
+ return -EINVAL;
+
+ if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
+ return -EALREADY;
+
+ change_bit(HCI_FORCE_LESC, &hdev->dbg_flags);
+
+ return count;
+}
+
+static const struct file_operations force_lesc_support_fops = {
+ .open = simple_open,
+ .read = force_lesc_support_read,
+ .write = force_lesc_support_write,
+ .llseek = default_llseek,
+};
+
static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1817,6 +1860,10 @@ static int __hci_init(struct hci_dev *hdev)
hdev, &force_sc_support_fops);
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
hdev, &sc_only_mode_fops);
+ if (lmp_le_capable(hdev))
+ debugfs_create_file("force_lesc_support", 0644,
+ hdev->debugfs, hdev,
+ &force_lesc_support_fops);
}
if (lmp_sniff_capable(hdev)) {
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 36/49] Bluetooth: Add skeleton for BR/EDR SMP channel
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (34 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 35/49] Bluetooth: Add debugfs switch for forcing SMP over BR/EDR Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 37/49] Bluetooth: Add full SMP BR/EDR support Johan Hedberg
` (13 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds the very basic code for creating and destroying SMP
L2CAP channels for BR/EDR connections.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 1 +
include/net/bluetooth/l2cap.h | 2 +
net/bluetooth/smp.c | 89 ++++++++++++++++++++++++++++++++--------
3 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 42f9362a83c1..f39e65096b1f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -306,6 +306,7 @@ struct hci_dev {
__u32 req_result;
void *smp_data;
+ void *smp_bredr_data;
struct discovery_state discovery;
struct hci_conn_hash conn_hash;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d71dc3579354..eee3ef530e79 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -141,6 +141,7 @@ struct l2cap_conninfo {
#define L2CAP_FC_ATT 0x10
#define L2CAP_FC_SIG_LE 0x20
#define L2CAP_FC_SMP_LE 0x40
+#define L2CAP_FC_SMP_BREDR 0x80
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000
@@ -255,6 +256,7 @@ struct l2cap_conn_rsp {
#define L2CAP_CID_ATT 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
+#define L2CAP_CID_SMP_BREDR 0x0007
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
#define L2CAP_CID_LE_DYN_END 0x007f
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3aad5864a5e1..8c1b53f32f10 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2504,6 +2504,9 @@ static void smp_resume_cb(struct l2cap_chan *chan)
BT_DBG("chan %p", chan);
+ if (hcon->type == ACL_LINK)
+ return;
+
if (!smp)
return;
@@ -2527,10 +2530,14 @@ static void smp_ready_cb(struct l2cap_chan *chan)
static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
+ struct hci_conn *hcon = chan->conn->hcon;
int err;
BT_DBG("chan %p", chan);
+ if (hcon->type == ACL_LINK)
+ return -EOPNOTSUPP;
+
err = smp_sig_channel(chan, skb);
if (err) {
struct smp_chan *smp = chan->data;
@@ -2627,34 +2634,40 @@ static const struct l2cap_ops smp_root_chan_ops = {
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
};
-int smp_register(struct hci_dev *hdev)
+static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
{
struct l2cap_chan *chan;
struct crypto_blkcipher *tfm_aes;
- BT_DBG("%s", hdev->name);
+ if (cid == L2CAP_CID_SMP_BREDR) {
+ tfm_aes = NULL;
+ goto create_chan;
+ }
tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0);
if (IS_ERR(tfm_aes)) {
- int err = PTR_ERR(tfm_aes);
BT_ERR("Unable to create crypto context");
- return err;
+ return ERR_PTR(PTR_ERR(tfm_aes));
}
+create_chan:
chan = l2cap_chan_create();
if (!chan) {
crypto_free_blkcipher(tfm_aes);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
chan->data = tfm_aes;
- l2cap_add_scid(chan, L2CAP_CID_SMP);
+ l2cap_add_scid(chan, cid);
l2cap_chan_set_defaults(chan);
bacpy(&chan->src, &hdev->bdaddr);
- chan->src_type = BDADDR_LE_PUBLIC;
+ if (cid == L2CAP_CID_SMP)
+ chan->src_type = BDADDR_LE_PUBLIC;
+ else
+ chan->src_type = BDADDR_BREDR;
chan->state = BT_LISTEN;
chan->mode = L2CAP_MODE_BASIC;
chan->imtu = L2CAP_DEFAULT_MTU;
@@ -2663,20 +2676,14 @@ int smp_register(struct hci_dev *hdev)
/* Set correct nesting level for a parent/listening channel */
atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
- hdev->smp_data = chan;
-
- return 0;
+ return chan;
}
-void smp_unregister(struct hci_dev *hdev)
+static void smp_del_chan(struct l2cap_chan *chan)
{
- struct l2cap_chan *chan = hdev->smp_data;
- struct crypto_blkcipher *tfm_aes;
-
- if (!chan)
- return;
+ struct crypto_blkcipher *tfm_aes;
- BT_DBG("%s chan %p", hdev->name, chan);
+ BT_DBG("chan %p", chan);
tfm_aes = chan->data;
if (tfm_aes) {
@@ -2684,6 +2691,52 @@ void smp_unregister(struct hci_dev *hdev)
crypto_free_blkcipher(tfm_aes);
}
- hdev->smp_data = NULL;
l2cap_chan_put(chan);
}
+
+int smp_register(struct hci_dev *hdev)
+{
+ struct l2cap_chan *chan;
+
+ BT_DBG("%s", hdev->name);
+
+ chan = smp_add_cid(hdev, L2CAP_CID_SMP);
+ if (IS_ERR(chan))
+ return PTR_ERR(chan);
+
+ hdev->smp_data = chan;
+
+ if (!lmp_sc_capable(hdev) &&
+ !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
+ return 0;
+
+ chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
+ if (IS_ERR(chan)) {
+ int err = PTR_ERR(chan);
+ chan = hdev->smp_data;
+ hdev->smp_data = NULL;
+ smp_del_chan(chan);
+ return err;
+ }
+
+ hdev->smp_bredr_data = chan;
+
+ return 0;
+}
+
+void smp_unregister(struct hci_dev *hdev)
+{
+ struct l2cap_chan *chan;
+
+ if (hdev->smp_bredr_data) {
+ chan = hdev->smp_bredr_data;
+ hdev->smp_bredr_data = NULL;
+ smp_del_chan(chan);
+ }
+
+ if (hdev->smp_data) {
+ chan = hdev->smp_data;
+ hdev->smp_data = NULL;
+ smp_del_chan(chan);
+ }
+}
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 37/49] Bluetooth: Add full SMP BR/EDR support
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (35 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 36/49] Bluetooth: Add skeleton for BR/EDR SMP channel Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 38/49] Bluetooth: Add SC-only mode support for SMP Johan Hedberg
` (12 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
When doing SMP over BR/EDR some of the routines can be shared with the
LE functionality whereas others needs to be split into their own BR/EDR
specific branches. This patch implements the split of BR/EDR specific
SMP code from the LE-only code, making sure SMP over BR/EDR works as
specified.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_core.c | 4 +
net/bluetooth/smp.c | 230 ++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 212 insertions(+), 22 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 43349ed4c249..a8da7ea9c2c0 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6967,6 +6967,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags))
conn->local_fixed_chan |= L2CAP_FC_A2MP;
+ if (bredr_sc_enabled(hcon->hdev) &&
+ test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
+ conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
+
mutex_init(&conn->ident_lock);
mutex_init(&conn->chan_lock);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 8c1b53f32f10..12294935d258 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -915,11 +915,13 @@ static void smp_notify_keys(struct l2cap_conn *conn)
mgmt_new_irk(hdev, smp->remote_irk);
/* Now that user space can be considered to know the
* identity address track the connection based on it
- * from now on.
+ * from now on (assuming this is an LE link).
*/
- bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
- hcon->dst_type = smp->remote_irk->addr_type;
- queue_work(hdev->workqueue, &conn->id_addr_update_work);
+ if (hcon->type == LE_LINK) {
+ bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
+ hcon->dst_type = smp->remote_irk->addr_type;
+ queue_work(hdev->workqueue, &conn->id_addr_update_work);
+ }
/* When receiving an indentity resolving key for
* a remote device that does not use a resolvable
@@ -938,10 +940,20 @@ static void smp_notify_keys(struct l2cap_conn *conn)
}
}
- /* The LTKs and CSRKs should be persistent only if both sides
- * had the bonding bit set in their authentication requests.
- */
- persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
+ if (hcon->type == ACL_LINK) {
+ if (hcon->key_type == HCI_LK_DEBUG_COMBINATION)
+ persistent = false;
+ else
+ persistent = !test_bit(HCI_CONN_FLUSH_KEY,
+ &hcon->flags);
+ } else {
+ /* The LTKs and CSRKs should be persistent only if both sides
+ * had the bonding bit set in their authentication requests.
+ */
+ persistent = !!((req->auth_req & rsp->auth_req) &
+ SMP_AUTH_BONDING);
+ }
+
if (smp->csrk) {
smp->csrk->bdaddr_type = hcon->dst_type;
@@ -1057,6 +1069,35 @@ static void smp_allow_key_dist(struct smp_chan *smp)
SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO);
}
+static void sc_generate_ltk(struct smp_chan *smp)
+{
+ /* These constants are as specified in the core specification.
+ * In ASCII they spell out to 'tmp2' and 'brle'.
+ */
+ const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+ const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
+ struct hci_conn *hcon = smp->conn->hcon;
+ struct hci_dev *hdev = hcon->hdev;
+ struct link_key *key;
+
+ key = hci_find_link_key(hdev, &hcon->dst);
+ if (!key) {
+ BT_ERR("%s No Link Key found to generate LTK", hdev->name);
+ return;
+ }
+
+ if (key->type == HCI_LK_DEBUG_COMBINATION)
+ set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
+
+ if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
+ return;
+
+ if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
+ return;
+
+ sc_add_ltk(smp);
+}
+
static void smp_distribute_keys(struct smp_chan *smp)
{
struct smp_cmd_pairing *req, *rsp;
@@ -1086,8 +1127,10 @@ static void smp_distribute_keys(struct smp_chan *smp)
}
if (test_bit(SMP_FLAG_SC, &smp->flags)) {
- if (*keydist & SMP_DIST_LINK_KEY)
+ if (hcon->type == LE_LINK && (*keydist & SMP_DIST_LINK_KEY))
sc_generate_link_key(smp);
+ if (hcon->type == ACL_LINK && (*keydist & SMP_DIST_ENC_KEY))
+ sc_generate_ltk(smp);
/* Clear the keys which are generated but not distributed */
*keydist &= ~SMP_SC_NO_DIST;
@@ -1493,6 +1536,46 @@ unlock:
return err;
}
+static void build_bredr_pairing_cmd(struct smp_chan *smp,
+ struct smp_cmd_pairing *req,
+ struct smp_cmd_pairing *rsp)
+{
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_dev *hdev = conn->hcon->hdev;
+ u8 local_dist = 0, remote_dist = 0;
+
+ if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) {
+ local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
+ remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
+ }
+
+ if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
+ remote_dist |= SMP_DIST_ID_KEY;
+
+ if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
+ local_dist |= SMP_DIST_ID_KEY;
+
+ if (!rsp) {
+ memset(req, 0, sizeof(*req));
+
+ req->init_key_dist = local_dist;
+ req->resp_key_dist = remote_dist;
+ req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+
+ smp->remote_key_dist = remote_dist;
+
+ return;
+ }
+
+ memset(rsp, 0, sizeof(*rsp));
+
+ rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ rsp->init_key_dist = req->init_key_dist & remote_dist;
+ rsp->resp_key_dist = req->resp_key_dist & local_dist;
+
+ smp->remote_key_dist = rsp->init_key_dist;
+}
+
static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
@@ -1529,6 +1612,31 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
memcpy(&smp->preq[1], req, sizeof(*req));
skb_pull(skb, sizeof(*req));
+ /* SMP over BR/EDR requires special treatment */
+ if (conn->hcon->type == ACL_LINK) {
+ /* We must have a BR/EDR SC link */
+ if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags))
+ return SMP_CROSS_TRANSP_NOT_ALLOWED;
+
+ set_bit(SMP_FLAG_SC, &smp->flags);
+
+ build_bredr_pairing_cmd(smp, req, &rsp);
+
+ key_size = min(req->max_key_size, rsp.max_key_size);
+ if (check_enc_key_size(conn, key_size))
+ return SMP_ENC_KEY_SIZE;
+
+ /* Clear bits which are generated but not distributed */
+ smp->remote_key_dist &= ~SMP_SC_NO_DIST;
+
+ smp->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
+
+ smp_distribute_keys(smp);
+ return 0;
+ }
+
build_pairing_cmd(conn, req, &rsp, auth);
if (rsp.auth_req & SMP_AUTH_SC)
@@ -1644,6 +1752,22 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
+ smp->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
+
+ /* Update remote key distribution in case the remote cleared
+ * some bits that we had enabled in our request.
+ */
+ smp->remote_key_dist &= rsp->resp_key_dist;
+
+ /* For BR/EDR this means we're done and can start phase 3 */
+ if (conn->hcon->type == ACL_LINK) {
+ /* Clear bits which are generated but not distributed */
+ smp->remote_key_dist &= ~SMP_SC_NO_DIST;
+ smp_distribute_keys(smp);
+ return 0;
+ }
+
if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC))
set_bit(SMP_FLAG_SC, &smp->flags);
else if (conn->hcon->pending_sec_level > BT_SECURITY_HIGH)
@@ -1661,9 +1785,6 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
get_random_bytes(smp->prnd, sizeof(smp->prnd));
- smp->prsp[0] = SMP_CMD_PAIRING_RSP;
- memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
-
/* Update remote key distribution in case the remote cleared
* some bits that we had enabled in our request.
*/
@@ -2373,11 +2494,6 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
__u8 code, reason;
int err = 0;
- if (hcon->type != LE_LINK) {
- kfree_skb(skb);
- return 0;
- }
-
if (skb->len < 1)
return -EILSEQ;
@@ -2496,6 +2612,74 @@ static void smp_teardown_cb(struct l2cap_chan *chan, int err)
l2cap_chan_put(chan);
}
+static void bredr_pairing(struct l2cap_chan *chan)
+{
+ struct l2cap_conn *conn = chan->conn;
+ struct hci_conn *hcon = conn->hcon;
+ struct hci_dev *hdev = hcon->hdev;
+ struct smp_cmd_pairing req;
+ struct smp_chan *smp;
+
+ BT_DBG("chan %p", chan);
+
+ /* Only new pairings are interesting */
+ if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags))
+ return;
+
+ /* Don't bother if we're not encrypted */
+ if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
+ return;
+
+ /* Only master may initiate SMP over BR/EDR */
+ if (hcon->role != HCI_ROLE_MASTER)
+ return;
+
+ /* Secure Connections support must be enabled */
+ if (!test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
+ return;
+
+ /* BR/EDR must use Secure Connections for SMP */
+ if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
+ !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
+ return;
+
+ /* If our LE support is not enabled don't do anything */
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ return;
+
+ /* Don't bother if remote LE support is not enabled */
+ if (!lmp_host_le_capable(hcon))
+ return;
+
+ /* Remote must support SMP fixed chan for BR/EDR */
+ if (!(conn->remote_fixed_chan & L2CAP_FC_SMP_BREDR))
+ return;
+
+ /* Don't bother if SMP is already ongoing */
+ if (chan->data)
+ return;
+
+ smp = smp_chan_create(conn);
+ if (!smp) {
+ BT_ERR("%s unable to create SMP context for BR/EDR",
+ hdev->name);
+ return;
+ }
+
+ set_bit(SMP_FLAG_SC, &smp->flags);
+
+ BT_DBG("%s starting SMP over BR/EDR", hdev->name);
+
+ /* Prepare and send the BR/EDR SMP Pairing Request */
+ build_bredr_pairing_cmd(smp, &req, NULL);
+
+ smp->preq[0] = SMP_CMD_PAIRING_REQ;
+ memcpy(&smp->preq[1], &req, sizeof(req));
+
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req);
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
+}
+
static void smp_resume_cb(struct l2cap_chan *chan)
{
struct smp_chan *smp = chan->data;
@@ -2504,8 +2688,10 @@ static void smp_resume_cb(struct l2cap_chan *chan)
BT_DBG("chan %p", chan);
- if (hcon->type == ACL_LINK)
+ if (hcon->type == ACL_LINK) {
+ bredr_pairing(chan);
return;
+ }
if (!smp)
return;
@@ -2521,23 +2707,23 @@ static void smp_resume_cb(struct l2cap_chan *chan)
static void smp_ready_cb(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
+ struct hci_conn *hcon = conn->hcon;
BT_DBG("chan %p", chan);
conn->smp = chan;
l2cap_chan_hold(chan);
+
+ if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
+ bredr_pairing(chan);
}
static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
- struct hci_conn *hcon = chan->conn->hcon;
int err;
BT_DBG("chan %p", chan);
- if (hcon->type == ACL_LINK)
- return -EOPNOTSUPP;
-
err = smp_sig_channel(chan, skb);
if (err) {
struct smp_chan *smp = chan->data;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 38/49] Bluetooth: Add SC-only mode support for SMP
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (36 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 37/49] Bluetooth: Add full SMP BR/EDR support Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 39/49] Bluetooth: Unify remote OOB data functions Johan Hedberg
` (11 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
When Secure Connections-only mode is enabled we should reject any
pairing command that does not have Secure Connections set in the
authentication requirements. This patch adds the appropriate logic for
this to the command handlers of Pairing Request/Response and Security
Request.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 12294935d258..3a4579b3ab06 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1608,6 +1608,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
(auth & SMP_AUTH_BONDING))
return SMP_PAIRING_NOTSUPP;
+ if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+ return SMP_AUTH_REQUIREMENTS;
+
smp->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&smp->preq[1], req, sizeof(*req));
skb_pull(skb, sizeof(*req));
@@ -1752,6 +1755,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
+ if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+ return SMP_AUTH_REQUIREMENTS;
+
smp->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
@@ -2008,6 +2014,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rp->auth_req & AUTH_REQ_MASK(hdev);
+ if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+ return SMP_AUTH_REQUIREMENTS;
+
if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
else
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 39/49] Bluetooth: Unify remote OOB data functions
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (37 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 38/49] Bluetooth: Add SC-only mode support for SMP Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 40/49] Bluetooth: Store address type with OOB data Johan Hedberg
` (10 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
There's no need to duplicate code for the 192 vs 192+256 variants of the
OOB data functions. This is also helpful to pave the way to support LE
SC OOB data where only 256 bit data is provided.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 6 ++----
net/bluetooth/hci_core.c | 46 +++++++++++++---------------------------
net/bluetooth/mgmt.c | 9 ++++----
3 files changed, 22 insertions(+), 39 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f39e65096b1f..3e89ece75039 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -944,10 +944,8 @@ void hci_remote_oob_data_clear(struct hci_dev *hdev);
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
bdaddr_t *bdaddr);
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash, u8 *rand);
-int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash192, u8 *rand192,
- u8 *hash256, u8 *rand256);
+ u8 *hash192, u8 *rand192,
+ u8 *hash256, u8 *rand256);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 581e13e9dc32..967fbfe80f1f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3517,7 +3517,8 @@ void hci_remote_oob_data_clear(struct hci_dev *hdev)
}
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash, u8 *rand)
+ u8 *hash192, u8 *rand192,
+ u8 *hash256, u8 *rand256)
{
struct oob_data *data;
@@ -3531,38 +3532,21 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
list_add(&data->list, &hdev->remote_oob_data);
}
- memcpy(data->hash192, hash, sizeof(data->hash192));
- memcpy(data->rand192, rand, sizeof(data->rand192));
-
- memset(data->hash256, 0, sizeof(data->hash256));
- memset(data->rand256, 0, sizeof(data->rand256));
-
- BT_DBG("%s for %pMR", hdev->name, bdaddr);
-
- return 0;
-}
-
-int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash192, u8 *rand192,
- u8 *hash256, u8 *rand256)
-{
- struct oob_data *data;
-
- data = hci_find_remote_oob_data(hdev, bdaddr);
- if (!data) {
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- bacpy(&data->bdaddr, bdaddr);
- list_add(&data->list, &hdev->remote_oob_data);
+ if (hash192 && rand192) {
+ memcpy(data->hash192, hash192, sizeof(data->hash192));
+ memcpy(data->rand192, rand192, sizeof(data->rand192));
+ } else {
+ memset(data->hash192, 0, sizeof(data->hash192));
+ memset(data->rand192, 0, sizeof(data->rand192));
}
- memcpy(data->hash192, hash192, sizeof(data->hash192));
- memcpy(data->rand192, rand192, sizeof(data->rand192));
-
- memcpy(data->hash256, hash256, sizeof(data->hash256));
- memcpy(data->rand256, rand256, sizeof(data->rand256));
+ if (hash256 && rand256) {
+ memcpy(data->hash256, hash256, sizeof(data->hash256));
+ memcpy(data->rand256, rand256, sizeof(data->rand256));
+ } else {
+ memset(data->hash256, 0, sizeof(data->hash256));
+ memset(data->rand256, 0, sizeof(data->rand256));
+ }
BT_DBG("%s for %pMR", hdev->name, bdaddr);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6e8165364b7f..0d92ba99ca93 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3599,7 +3599,8 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
}
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->hash, cp->rand);
+ cp->hash, cp->rand,
+ NULL, NULL);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
@@ -3619,9 +3620,9 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}
- err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
- cp->hash192, cp->rand192,
- cp->hash256, cp->rand256);
+ err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
+ cp->hash192, cp->rand192,
+ cp->hash256, cp->rand256);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 40/49] Bluetooth: Store address type with OOB data
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (38 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 39/49] Bluetooth: Unify remote OOB data functions Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 41/49] Bluetooth: Add support for adding remote OOB data for LE Johan Hedberg
` (9 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
To be able to support OOB data for LE pairing we need to store the
address type of the remote device. This patch extends the relevant
functions and data types with a bdaddr_type variable.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 8 +++++---
net/bluetooth/hci_core.c | 26 ++++++++++++++++----------
net/bluetooth/hci_event.c | 4 ++--
net/bluetooth/mgmt.c | 11 ++++++-----
4 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3e89ece75039..1dae7001fc31 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -140,6 +140,7 @@ struct link_key {
struct oob_data {
struct list_head list;
bdaddr_t bdaddr;
+ u8 bdaddr_type;
u8 hash192[16];
u8 rand192[16];
u8 hash256[16];
@@ -942,11 +943,12 @@ void hci_smp_irks_clear(struct hci_dev *hdev);
void hci_remote_oob_data_clear(struct hci_dev *hdev);
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
- bdaddr_t *bdaddr);
+ bdaddr_t *bdaddr, u8 bdaddr_type);
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash192, u8 *rand192,
+ u8 bdaddr_type, u8 *hash192, u8 *rand192,
u8 *hash256, u8 *rand256);
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 bdaddr_type);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 967fbfe80f1f..c8123f04a33c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2160,7 +2160,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
- hci_remove_remote_oob_data(hdev, &data->bdaddr);
+ hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR);
if (!data->ssp_mode)
flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
@@ -3479,26 +3479,31 @@ static void hci_cmd_timeout(struct work_struct *work)
}
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
- bdaddr_t *bdaddr)
+ bdaddr_t *bdaddr, u8 bdaddr_type)
{
struct oob_data *data;
- list_for_each_entry(data, &hdev->remote_oob_data, list)
- if (bacmp(bdaddr, &data->bdaddr) == 0)
- return data;
+ list_for_each_entry(data, &hdev->remote_oob_data, list) {
+ if (bacmp(bdaddr, &data->bdaddr) != 0)
+ continue;
+ if (data->bdaddr_type != bdaddr_type)
+ continue;
+ return data;
+ }
return NULL;
}
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 bdaddr_type)
{
struct oob_data *data;
- data = hci_find_remote_oob_data(hdev, bdaddr);
+ data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
if (!data)
return -ENOENT;
- BT_DBG("%s removing %pMR", hdev->name, bdaddr);
+ BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
list_del(&data->list);
kfree(data);
@@ -3517,18 +3522,19 @@ void hci_remote_oob_data_clear(struct hci_dev *hdev)
}
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 *hash192, u8 *rand192,
+ u8 bdaddr_type, u8 *hash192, u8 *rand192,
u8 *hash256, u8 *rand256)
{
struct oob_data *data;
- data = hci_find_remote_oob_data(hdev, bdaddr);
+ data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
if (!data) {
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
bacpy(&data->bdaddr, bdaddr);
+ data->bdaddr_type = bdaddr_type;
list_add(&data->list, &hdev->remote_oob_data);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c3d6390e3b7b..f4e2a61bb6aa 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3773,7 +3773,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
cp.authentication = conn->auth_type;
- if (hci_find_remote_oob_data(hdev, &conn->dst) &&
+ if (hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR) &&
(conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
cp.oob_data = 0x01;
else
@@ -4028,7 +4028,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
goto unlock;
- data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
+ data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
if (data) {
if (bredr_sc_enabled(hdev)) {
struct hci_cp_remote_oob_ext_data_reply cp;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0d92ba99ca93..57de9f7222aa 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3599,8 +3599,8 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
}
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->hash, cp->rand,
- NULL, NULL);
+ cp->addr.type, cp->hash,
+ cp->rand, NULL, NULL);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
@@ -3621,8 +3621,9 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
}
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->hash192, cp->rand192,
- cp->hash256, cp->rand256);
+ cp->addr.type, cp->hash192,
+ cp->rand192, cp->hash256,
+ cp->rand256);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
@@ -3663,7 +3664,7 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
goto done;
}
- err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
+ err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
if (err < 0)
status = MGMT_STATUS_INVALID_PARAMS;
else
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 41/49] Bluetooth: Add support for adding remote OOB data for LE
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (39 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 40/49] Bluetooth: Store address type with OOB data Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 42/49] Bluetooth: Set SMP OOB flag if OOB data is available Johan Hedberg
` (8 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds proper support for passing LE OOB data to the
hci_add_remote_oob_data() function. For LE the 192-bit values are not
valid and should therefore be passed as NULL values.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 57de9f7222aa..1e73bead7dd9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3610,6 +3610,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
status, &cp->addr, sizeof(cp->addr));
} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
struct mgmt_cp_add_remote_oob_ext_data *cp = data;
+ u8 *rand192, *hash192;
u8 status;
if (cp->addr.type != BDADDR_BREDR) {
@@ -3620,10 +3621,17 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}
+ if (bdaddr_type_is_le(cp->addr.type)) {
+ rand192 = NULL;
+ hash192 = NULL;
+ } else {
+ rand192 = cp->rand192;
+ hash192 = cp->hash192;
+ }
+
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->addr.type, cp->hash192,
- cp->rand192, cp->hash256,
- cp->rand256);
+ cp->addr.type, hash192, rand192,
+ cp->hash256, cp->rand256);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 42/49] Bluetooth: Set SMP OOB flag if OOB data is available
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (40 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 41/49] Bluetooth: Add support for adding remote OOB data for LE Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 43/49] Bluetooth: Add basic LE SC OOB support for remote OOB data Johan Hedberg
` (7 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
If we have OOB data available for the remote device in question we
should set the OOB flag appropriately in the SMP pairing request or
response.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3a4579b3ab06..a38541d079f5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -57,6 +57,7 @@ enum {
SMP_FLAG_DEBUG_KEY,
SMP_FLAG_WAIT_USER,
SMP_FLAG_DHKEY_PENDING,
+ SMP_FLAG_OOB,
};
struct smp_chan {
@@ -562,7 +563,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
struct smp_chan *smp = chan->data;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
- u8 local_dist = 0, remote_dist = 0;
+ u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) {
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
@@ -578,19 +579,37 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
local_dist |= SMP_DIST_ID_KEY;
- if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
- if ((authreq & SMP_AUTH_SC) &&
- test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+ (authreq & SMP_AUTH_SC)) {
+ struct oob_data *oob_data;
+ u8 bdaddr_type;
+
+ if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
local_dist |= SMP_DIST_LINK_KEY;
remote_dist |= SMP_DIST_LINK_KEY;
}
+
+ if (hcon->dst_type == ADDR_LE_DEV_PUBLIC)
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else
+ bdaddr_type = BDADDR_LE_RANDOM;
+
+ oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
+ bdaddr_type);
+ if (oob_data) {
+ set_bit(SMP_FLAG_OOB, &smp->flags);
+ oob_flag = SMP_OOB_PRESENT;
+ memcpy(smp->rrnd, oob_data->rand256, 16);
+ memcpy(smp->pcnf, oob_data->hash256, 16);
+ }
+
} else {
authreq &= ~SMP_AUTH_SC;
}
if (rsp == NULL) {
req->io_capability = conn->hcon->io_capability;
- req->oob_flag = SMP_OOB_NOT_PRESENT;
+ req->oob_flag = oob_flag;
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
req->init_key_dist = local_dist;
req->resp_key_dist = remote_dist;
@@ -601,7 +620,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
}
rsp->io_capability = conn->hcon->io_capability;
- rsp->oob_flag = SMP_OOB_NOT_PRESENT;
+ rsp->oob_flag = oob_flag;
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
rsp->init_key_dist = req->init_key_dist & remote_dist;
rsp->resp_key_dist = req->resp_key_dist & local_dist;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 43/49] Bluetooth: Add basic LE SC OOB support for remote OOB data
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (41 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 42/49] Bluetooth: Set SMP OOB flag if OOB data is available Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 44/49] Bluetooth: Introduce SMP_DBG macro for low-level debuging Johan Hedberg
` (6 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds basic OOB pairing support when we've received the remote
OOB data. This includes tracking the remote r value (in smp->rr) as well
as doing the appropriate f4() call when needed. Previously the OOB rand
would have been stored in smp->rrnd however these are actually two
independent values so we need separate variables for them. Na/Nb in the
spec maps to smp->prnd/rrnd and ra/rb maps to smp->rr with smp->pr to
come once local OOB data is supported.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 38 ++++++++++++++++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a38541d079f5..62ca2aaf72fa 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -71,6 +71,7 @@ struct smp_chan {
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */
+ u8 rr[16];
u8 enc_key_size;
u8 remote_key_dist;
bdaddr_t id_addr;
@@ -599,7 +600,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
if (oob_data) {
set_bit(SMP_FLAG_OOB, &smp->flags);
oob_flag = SMP_OOB_PRESENT;
- memcpy(smp->rrnd, oob_data->rand256, 16);
+ memcpy(smp->rr, oob_data->rand256, 16);
memcpy(smp->pcnf, oob_data->hash256, 16);
}
@@ -1334,6 +1335,9 @@ static void sc_dhkey_check(struct smp_chan *smp)
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
put_unaligned_le32(hcon->passkey_notify, r);
+ if (smp->method == REQ_OOB)
+ memcpy(r, smp->rr, 16);
+
smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
local_addr, remote_addr, check.e);
@@ -1910,6 +1914,14 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (!test_bit(SMP_FLAG_SC, &smp->flags))
return smp_random(smp);
+ if (smp->method == REQ_OOB) {
+ if (!hcon->out)
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
+ sizeof(smp->prnd), smp->prnd);
+ SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+ goto mackey_and_ltk;
+ }
+
/* Passkey entry has special treatment */
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
@@ -1940,12 +1952,13 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
nb = smp->prnd;
}
+mackey_and_ltk:
/* Generate MacKey and LTK */
err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk);
if (err)
return SMP_UNSPECIFIED;
- if (smp->method == JUST_WORKS) {
+ if (smp->method == JUST_WORKS || smp->method == REQ_OOB) {
if (hcon->out) {
sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
@@ -2314,6 +2327,9 @@ static u8 sc_select_method(struct smp_chan *smp)
struct smp_cmd_pairing *local, *remote;
u8 local_mitm, remote_mitm, local_io, remote_io, method;
+ if (test_bit(SMP_FLAG_OOB, &smp->flags))
+ return REQ_OOB;
+
/* The preq/prsp contain the raw Pairing Request/Response PDUs
* which are needed as inputs to some crypto functions. To get
* the "struct smp_cmd_pairing" from them we need to skip the
@@ -2412,6 +2428,24 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
}
+ if (smp->method == REQ_OOB) {
+ err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
+ smp->rr, 0, cfm.confirm_val);
+ if (err)
+ return SMP_UNSPECIFIED;
+
+ if (memcmp(cfm.confirm_val, smp->pcnf, 16))
+ return SMP_CONFIRM_FAILED;
+
+ if (hcon->out)
+ smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
+ sizeof(smp->prnd), smp->prnd);
+
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
+
+ return 0;
+ }
+
if (hcon->out)
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 44/49] Bluetooth: Introduce SMP_DBG macro for low-level debuging
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (42 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 43/49] Bluetooth: Add basic LE SC OOB support for remote OOB data Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 45/49] Bluetooth: Fix missing const declarations in SMP functions Johan Hedberg
` (5 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The various inputs & outputs of the crypto functions as well as the
values of the ECDH keys can be considered security sensitive. They
should therefore not end up in dmesg by mistake. This patch introduces a
new SMP_DBG macro which requires explicit compilation with -DDEBUG to be
enabled. All crypto related data logs now use this macro instead of
BT_DBG.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 68 +++++++++++++++++++++++++++++++----------------------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 62ca2aaf72fa..7839354592f4 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -32,6 +32,18 @@
#include "ecc.h"
#include "smp.h"
+/* Low-level debug macros to be used for stuff that we don't want
+ * accidentially in dmesg, i.e. the values of the various crypto keys
+ * and the inputs & outputs of crypto functions.
+ */
+#ifdef DEBUG
+#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__)
+#else
+#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__)
+#endif
+
#define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd)
/* Keys which are not distributed with Secure Connections */
@@ -154,8 +166,8 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
swap_buf(k, tmp, 16);
swap_buf(m, msg_msb, len);
- BT_DBG("msg (len %zu) %*phN", len, len, m);
- BT_DBG("key %16phN", k);
+ SMP_DBG("msg (len %zu) %*phN", len, len, m);
+ SMP_DBG("key %16phN", k);
err = crypto_hash_setkey(tfm, tmp, 16);
if (err) {
@@ -179,7 +191,7 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
swap_buf(mac_msb, mac, 16);
- BT_DBG("mac %16phN", mac);
+ SMP_DBG("mac %16phN", mac);
return 0;
}
@@ -190,9 +202,9 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
u8 m[65];
int err;
- BT_DBG("u %32phN", u);
- BT_DBG("v %32phN", v);
- BT_DBG("x %16phN z %02x", x, z);
+ SMP_DBG("u %32phN", u);
+ SMP_DBG("v %32phN", v);
+ SMP_DBG("x %16phN z %02x", x, z);
m[0] = z;
memcpy(m + 1, v, 32);
@@ -202,7 +214,7 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
if (err)
return err;
- BT_DBG("res %16phN", res);
+ SMP_DBG("res %16phN", res);
return err;
}
@@ -223,15 +235,15 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
u8 m[53], t[16];
int err;
- BT_DBG("w %32phN", w);
- BT_DBG("n1 %16phN n2 %16phN", n1, n2);
- BT_DBG("a1 %7phN a2 %7phN", a1, a2);
+ SMP_DBG("w %32phN", w);
+ SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
+ SMP_DBG("a1 %7phN a2 %7phN", a1, a2);
err = aes_cmac(tfm_cmac, salt, w, 32, t);
if (err)
return err;
- BT_DBG("t %16phN", t);
+ SMP_DBG("t %16phN", t);
memcpy(m, length, 2);
memcpy(m + 2, a2, 7);
@@ -246,7 +258,7 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
if (err)
return err;
- BT_DBG("mackey %16phN", mackey);
+ SMP_DBG("mackey %16phN", mackey);
m[52] = 1; /* Counter */
@@ -254,7 +266,7 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
if (err)
return err;
- BT_DBG("ltk %16phN", ltk);
+ SMP_DBG("ltk %16phN", ltk);
return 0;
}
@@ -267,9 +279,9 @@ static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16],
u8 m[65];
int err;
- BT_DBG("w %16phN", w);
- BT_DBG("n1 %16phN n2 %16phN", n1, n2);
- BT_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
+ SMP_DBG("w %16phN", w);
+ SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
+ SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
memcpy(m, a2, 7);
memcpy(m + 7, a1, 7);
@@ -293,9 +305,9 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
u8 m[80], tmp[16];
int err;
- BT_DBG("u %32phN", u);
- BT_DBG("v %32phN", v);
- BT_DBG("x %16phN y %16phN", x, y);
+ SMP_DBG("u %32phN", u);
+ SMP_DBG("v %32phN", v);
+ SMP_DBG("x %16phN y %16phN", x, y);
memcpy(m, y, 16);
memcpy(m + 16, v, 32);
@@ -308,7 +320,7 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
*val = get_unaligned_le32(tmp);
*val %= 1000000;
- BT_DBG("val %06u", *val);
+ SMP_DBG("val %06u", *val);
return 0;
}
@@ -357,13 +369,13 @@ static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
{
int err;
- BT_DBG("w %16phN key_id %4phN", w, key_id);
+ SMP_DBG("w %16phN key_id %4phN", w, key_id);
err = aes_cmac(tfm_cmac, w, key_id, 4, res);
if (err)
return err;
- BT_DBG("res %16phN", res);
+ SMP_DBG("res %16phN", res);
return err;
}
@@ -1742,9 +1754,9 @@ static u8 sc_send_public_key(struct smp_chan *smp)
}
}
- BT_DBG("Local Public Key X: %32phN", smp->local_pk);
- BT_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
- BT_DBG("Local Private Key: %32phN", smp->local_sk);
+ SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
+ SMP_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
+ SMP_DBG("Local Private Key: %32phN", smp->local_sk);
smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
@@ -2390,13 +2402,13 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
return err;
}
- BT_DBG("Remote Public Key X: %32phN", smp->remote_pk);
- BT_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
+ SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
+ SMP_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
return SMP_UNSPECIFIED;
- BT_DBG("DHKey %32phN", smp->dhkey);
+ SMP_DBG("DHKey %32phN", smp->dhkey);
set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 45/49] Bluetooth: Fix missing const declarations in SMP functions
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (43 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 44/49] Bluetooth: Introduce SMP_DBG macro for low-level debuging Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 46/49] Bluetooth: Organize SMP crypto functions to logical sections Johan Hedberg
` (4 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Several SMP functions take read-only data. This patch fixes the
declaration of these parameters to use the const specifier as
appropriate.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 18 ++++++++++--------
net/bluetooth/smp.h | 5 +++--
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7839354592f4..423e99d13207 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -380,7 +380,8 @@ static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
return err;
}
-static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
+static int smp_ah(struct crypto_blkcipher *tfm, const u8 irk[16],
+ const u8 r[3], u8 res[3])
{
u8 _res[16];
int err;
@@ -406,7 +407,8 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
return 0;
}
-bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
+ const bdaddr_t *bdaddr)
{
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
@@ -427,7 +429,7 @@ bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
return !memcmp(bdaddr->b, hash, 3);
}
-int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
+int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
{
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
@@ -452,9 +454,9 @@ int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
return 0;
}
-static int smp_c1(struct crypto_blkcipher *tfm_aes, u8 k[16], u8 r[16],
- u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat,
- bdaddr_t *ra, u8 res[16])
+static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+ const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
+ const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
{
u8 p1[16], p2[16];
int err;
@@ -493,8 +495,8 @@ static int smp_c1(struct crypto_blkcipher *tfm_aes, u8 k[16], u8 r[16],
return err;
}
-static int smp_s1(struct crypto_blkcipher *tfm_aes, u8 k[16], u8 r1[16],
- u8 r2[16], u8 _r[16])
+static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+ const u8 r1[16], const u8 r2[16], u8 _r[16])
{
int err;
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index f955d6b7ceb2..3296bf42ae80 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -185,8 +185,9 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
-bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
-int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
+bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
+ const bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa);
int smp_register(struct hci_dev *hdev);
void smp_unregister(struct hci_dev *hdev);
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 46/49] Bluetooth: Organize SMP crypto functions to logical sections
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (44 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 45/49] Bluetooth: Fix missing const declarations in SMP functions Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 47/49] Bluetooth: Fix SMP debug key handling Johan Hedberg
` (3 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch organizes the various SMP crypto functions so that the LE SC
functions appear in one section and the legacy SMP functions in a
separate one.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 134 ++++++++++++++++++++++++++++------------------------
1 file changed, 71 insertions(+), 63 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 423e99d13207..c5dcb6563579 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -141,6 +141,10 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
dst[len - 1 - i] = src[i];
}
+/* The following functions map to the LE SC SMP crypto functions
+ * AES-CMAC, f4, f5, f6, g2 and h6.
+ */
+
static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
size_t len, u8 mac[16])
{
@@ -325,6 +329,26 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
return 0;
}
+static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
+ const u8 key_id[4], u8 res[16])
+{
+ int err;
+
+ SMP_DBG("w %16phN key_id %4phN", w, key_id);
+
+ err = aes_cmac(tfm_cmac, w, key_id, 4, res);
+ if (err)
+ return err;
+
+ SMP_DBG("res %16phN", res);
+
+ return err;
+}
+
+/* The following functions map to the legacy SMP crypto functions e, c1,
+ * s1 and ah.
+ */
+
static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
{
struct blkcipher_desc desc;
@@ -364,18 +388,59 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
return err;
}
-static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
- const u8 key_id[4], u8 res[16])
+static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+ const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
+ const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
{
+ u8 p1[16], p2[16];
int err;
- SMP_DBG("w %16phN key_id %4phN", w, key_id);
+ memset(p1, 0, 16);
- err = aes_cmac(tfm_cmac, w, key_id, 4, res);
- if (err)
+ /* p1 = pres || preq || _rat || _iat */
+ p1[0] = _iat;
+ p1[1] = _rat;
+ memcpy(p1 + 2, preq, 7);
+ memcpy(p1 + 9, pres, 7);
+
+ /* p2 = padding || ia || ra */
+ memcpy(p2, ra, 6);
+ memcpy(p2 + 6, ia, 6);
+ memset(p2 + 12, 0, 4);
+
+ /* res = r XOR p1 */
+ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm_aes, k, res);
+ if (err) {
+ BT_ERR("Encrypt data error");
return err;
+ }
- SMP_DBG("res %16phN", res);
+ /* res = res XOR p2 */
+ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+ /* res = e(k, res) */
+ err = smp_e(tfm_aes, k, res);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+ const u8 r1[16], const u8 r2[16], u8 _r[16])
+{
+ int err;
+
+ /* Just least significant octets from r1 and r2 are considered */
+ memcpy(_r, r2, 8);
+ memcpy(_r + 8, r1, 8);
+
+ err = smp_e(tfm_aes, k, _r);
+ if (err)
+ BT_ERR("Encrypt data error");
return err;
}
@@ -454,63 +519,6 @@ int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
return 0;
}
-static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
- const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
- const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
-{
- u8 p1[16], p2[16];
- int err;
-
- memset(p1, 0, 16);
-
- /* p1 = pres || preq || _rat || _iat */
- p1[0] = _iat;
- p1[1] = _rat;
- memcpy(p1 + 2, preq, 7);
- memcpy(p1 + 9, pres, 7);
-
- /* p2 = padding || ia || ra */
- memcpy(p2, ra, 6);
- memcpy(p2 + 6, ia, 6);
- memset(p2 + 12, 0, 4);
-
- /* res = r XOR p1 */
- u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
-
- /* res = e(k, res) */
- err = smp_e(tfm_aes, k, res);
- if (err) {
- BT_ERR("Encrypt data error");
- return err;
- }
-
- /* res = res XOR p2 */
- u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
-
- /* res = e(k, res) */
- err = smp_e(tfm_aes, k, res);
- if (err)
- BT_ERR("Encrypt data error");
-
- return err;
-}
-
-static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
- const u8 r1[16], const u8 r2[16], u8 _r[16])
-{
- int err;
-
- /* Just least significant octets from r1 and r2 are considered */
- memcpy(_r, r2, 8);
- memcpy(_r + 8, r1, 8);
-
- err = smp_e(tfm_aes, k, _r);
- if (err)
- BT_ERR("Encrypt data error");
-
- return err;
-}
-
static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
{
struct l2cap_chan *chan = conn->smp;
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 47/49] Bluetooth: Fix SMP debug key handling
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (45 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 46/49] Bluetooth: Organize SMP crypto functions to logical sections Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 48/49] Bluetooth: Fix minor coding style issue in smp.c Johan Hedberg
` (2 subsequent siblings)
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
We need to keep debug keys around at least until the point that they are
used - otherwise e.g. slave role behavior wouldn't work as there'd be no
key to be looked up. The correct behavior should therefore be to return
any stored keys but when we clean up the SMP context to remove the key
from the hdev list if keeping debug keys around hasn't been requestsed.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/hci_core.c | 10 +---------
net/bluetooth/smp.c | 15 +++++++++++++--
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c8123f04a33c..f0018562b028 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3246,15 +3246,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
continue;
- if (smp_ltk_is_sc(k)) {
- if (k->type == SMP_LTK_P256_DEBUG &&
- !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
- continue;
- rcu_read_unlock();
- return k;
- }
-
- if (ltk_role(k->type) == role) {
+ if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
rcu_read_unlock();
return k;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index c5dcb6563579..aeae4bed7ded 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -670,6 +670,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
{
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_conn *hcon = conn->hcon;
bool complete;
BUG_ON(!smp);
@@ -677,7 +678,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
cancel_delayed_work_sync(&smp->security_timer);
complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
- mgmt_smp_complete(conn->hcon, complete);
+ mgmt_smp_complete(hcon, complete);
kfree(smp->csrk);
kfree(smp->slave_csrk);
@@ -686,6 +687,16 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
crypto_free_blkcipher(smp->tfm_aes);
crypto_free_hash(smp->tfm_cmac);
+ /* Ensure that we don't leave any debug key around if debug key
+ * support hasn't been explicitly enabled.
+ */
+ if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
+ !test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) {
+ list_del_rcu(&smp->ltk->list);
+ kfree_rcu(smp->ltk, rcu);
+ smp->ltk = NULL;
+ }
+
/* If pairing failed clean up any keys we might have */
if (!complete) {
if (smp->ltk) {
@@ -706,7 +717,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
chan->data = NULL;
kfree(smp);
- hci_conn_drop(conn->hcon);
+ hci_conn_drop(hcon);
}
static void smp_failure(struct l2cap_conn *conn, u8 reason)
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 48/49] Bluetooth: Fix minor coding style issue in smp.c
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (46 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 47/49] Bluetooth: Fix SMP debug key handling Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:02 ` [PATCH 49/49] Bluetooth: Fix false-positive "uninitialized" compiler warning Johan Hedberg
2014-12-03 15:56 ` [PATCH 00/49] Bluetooth: LE Secure Connections support Marcel Holtmann
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The convention for checking for NULL pointers is !ptr and not
ptr == NULL. This patch fixes such an occurrence in smp.c.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index aeae4bed7ded..96e2b329c8ce 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -356,7 +356,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
uint8_t tmp[16], data[16];
int err;
- if (tfm == NULL) {
+ if (!tfm) {
BT_ERR("tfm %p", tfm);
return -EINVAL;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH 49/49] Bluetooth: Fix false-positive "uninitialized" compiler warning
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (47 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 48/49] Bluetooth: Fix minor coding style issue in smp.c Johan Hedberg
@ 2014-12-03 15:02 ` Johan Hedberg
2014-12-03 15:56 ` [PATCH 00/49] Bluetooth: LE Secure Connections support Marcel Holtmann
49 siblings, 0 replies; 51+ messages in thread
From: Johan Hedberg @ 2014-12-03 15:02 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
Some gcc versions don't seem to be able to properly track the flow of
the smp_cmd_pairing_random() function and end up causing the following
types of (false-positive) warnings:
smp.c:1995:6: warning: ‘nb’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
smp.c:1995:6: warning: ‘na’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
^
smp.c:1995:6: warning: ‘pkbx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
^
smp.c:1995:6: warning: ‘pkax’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
This patch fixes the issue by moving the pkax/pkbx and na/nb
initialization earlier in the function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 96e2b329c8ce..53340e8f0b95 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1947,6 +1947,18 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (!test_bit(SMP_FLAG_SC, &smp->flags))
return smp_random(smp);
+ if (hcon->out) {
+ pkax = smp->local_pk;
+ pkbx = smp->remote_pk;
+ na = smp->prnd;
+ nb = smp->rrnd;
+ } else {
+ pkax = smp->remote_pk;
+ pkbx = smp->local_pk;
+ na = smp->rrnd;
+ nb = smp->prnd;
+ }
+
if (smp->method == REQ_OOB) {
if (!hcon->out)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
@@ -1969,20 +1981,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (memcmp(smp->pcnf, cfm, 16))
return SMP_CONFIRM_FAILED;
-
- pkax = smp->local_pk;
- pkbx = smp->remote_pk;
- na = smp->prnd;
- nb = smp->rrnd;
} else {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-
- pkax = smp->remote_pk;
- pkbx = smp->local_pk;
- na = smp->rrnd;
- nb = smp->prnd;
}
mackey_and_ltk:
--
2.1.0
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH 00/49] Bluetooth: LE Secure Connections support
2014-12-03 15:01 [PATCH 00/49] Bluetooth: LE Secure Connections support Johan Hedberg
` (48 preceding siblings ...)
2014-12-03 15:02 ` [PATCH 49/49] Bluetooth: Fix false-positive "uninitialized" compiler warning Johan Hedberg
@ 2014-12-03 15:56 ` Marcel Holtmann
49 siblings, 0 replies; 51+ messages in thread
From: Marcel Holtmann @ 2014-12-03 15:56 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
Hi Johan,
> First of all, appologies to all for this huge patch set. It's work from
> the past 6 months or so that wasn't releasable until the 4.2
> specification goes public. That happened just some moments ago:
>
> http://www.bluetooth.com/SiteCollectionDocuments/4-2/bluetooth4-2.aspx
>
> I'm sending the patches to the mailing list mainly for reference since
> Marcel will probably directly merge them from my tree. Any issues/fixes
> etc should be done on top of them.
>
> Johan
>
> ----------------------------------------------------------------
> Johan Hedberg (49):
> Bluetooth: Add basic SMP defines for LE Secure Connections
> Bluetooth: Make auth_req mask dependent on SC enabled or not
> Bluetooth: Add SMP flag for SC and set it when necessary.
> Bluetooth: Update SMP security level to/from auth_req for SC
> Bluetooth: Add mgmt support for LE Secure Connections LTK types
> Bluetooth: Set the correct security level for SC LTKs
> Bluetooth: Use custom macro for testing BR/EDR SC enabled
> Bluetooth: Add mgmt_set_secure_conn support for any LE adapter
> Bluetooth: Update LTK lookup to correctly deal with SC LTKs
> Bluetooth: Remove unused hci_find_ltk function
> Bluetooth: Rename hci_find_ltk_by_addr to hci_find_ltk
> Bluetooth: Set link key generation bit if necessary for LE SC
> Bluetooth: Add basic support for AES-CMAC
> Bluetooth: Add ECC library for LE Secure Connections
> Bluetooth: Add basic support for sending our LE SC public key
> Bluetooth: Add handler function for receiving LE SC public key
> Bluetooth: Add support for sending LE SC Confirm value
> Bluetooth: Add LE SC support for responding to Pairing Confirm PDU
> Bluetooth: Add support for LE SC numeric comparison
> Bluetooth: Add support for handling LE SC user response
> Bluetooth: Add support for LE SC DHKey check PDU
> Bluetooth: Add support for LE SC key generation
> Bluetooth: Track authentication method in SMP context
> Bluetooth: Add selection of the SC authentication method
> Bluetooth: Detect SMP SC debug keys
> Bluetooth: Add check for accidentally generating a debug key
> Bluetooth: Set correct LTK type and authentication for SC
> Bluetooth: Add support for SC just-works pairing
> Bluetooth: Fix BR/EDR Link Key type when derived through LE SC
> Bluetooth: Add passkey entry support for LE SC
> Bluetooth: Fix DHKey Check sending order for slave role
> Bluetooth: Add dummy handler for LE SC keypress notification
> Bluetooth: Use debug keys for SMP when HCI_USE_DEBUG_KEYS is set
> Bluetooth: Add hci_conn flag for new link key generation
> Bluetooth: Add debugfs switch for forcing SMP over BR/EDR
> Bluetooth: Add skeleton for BR/EDR SMP channel
> Bluetooth: Add full SMP BR/EDR support
> Bluetooth: Add SC-only mode support for SMP
> Bluetooth: Unify remote OOB data functions
> Bluetooth: Store address type with OOB data
> Bluetooth: Add support for adding remote OOB data for LE
> Bluetooth: Set SMP OOB flag if OOB data is available
> Bluetooth: Add basic LE SC OOB support for remote OOB data
> Bluetooth: Introduce SMP_DBG macro for low-level debuging
> Bluetooth: Fix missing const declarations in SMP functions
> Bluetooth: Organize SMP crypto functions to logical sections
> Bluetooth: Fix SMP debug key handling
> Bluetooth: Fix minor coding style issue in smp.c
> Bluetooth: Fix false-positive "uninitialized" compiler warning
>
> include/net/bluetooth/hci.h | 1 +
> include/net/bluetooth/hci_core.h | 23 +-
> include/net/bluetooth/l2cap.h | 2 +
> include/net/bluetooth/mgmt.h | 3 +
> net/bluetooth/Kconfig | 1 +
> net/bluetooth/Makefile | 2 +-
> net/bluetooth/ecc.c | 816 ++++++++++++++++++++
> net/bluetooth/ecc.h | 54 ++
> net/bluetooth/hci_core.c | 155 ++--
> net/bluetooth/hci_event.c | 23 +-
> net/bluetooth/l2cap_core.c | 4 +
> net/bluetooth/mgmt.c | 75 +-
> net/bluetooth/smp.c | 1543 +++++++++++++++++++++++++++++++++----
> net/bluetooth/smp.h | 51 +-
> 14 files changed, 2509 insertions(+), 244 deletions(-)
all 49 patches have been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply [flat|nested] 51+ messages in thread