diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-06-04 04:07:40 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-12-03 10:51:19 -0500 |
commit | d3e54a876e35120b3355e22d78861e73a6acab6f (patch) | |
tree | 05913c51782ceded2fcd6ed1fcba3b109a2facdf /net/bluetooth | |
parent | 38606f1418cc9c0ac4230f4d9133a2cae5e02416 (diff) |
Bluetooth: Fix DHKey Check sending order for slave role
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>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/smp.c | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8cfa1c1b205c..9a4ce4581475 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -56,6 +56,7 @@ enum { | |||
56 | SMP_FLAG_REMOTE_PK, | 56 | SMP_FLAG_REMOTE_PK, |
57 | SMP_FLAG_DEBUG_KEY, | 57 | SMP_FLAG_DEBUG_KEY, |
58 | SMP_FLAG_WAIT_USER, | 58 | SMP_FLAG_WAIT_USER, |
59 | SMP_FLAG_DHKEY_PENDING, | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | struct smp_chan { | 62 | struct smp_chan { |
@@ -994,6 +995,29 @@ static void smp_notify_keys(struct l2cap_conn *conn) | |||
994 | } | 995 | } |
995 | } | 996 | } |
996 | 997 | ||
998 | static void sc_add_ltk(struct smp_chan *smp) | ||
999 | { | ||
1000 | struct hci_conn *hcon = smp->conn->hcon; | ||
1001 | u8 key_type, auth; | ||
1002 | |||
1003 | if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags)) | ||
1004 | key_type = SMP_LTK_P256_DEBUG; | ||
1005 | else | ||
1006 | key_type = SMP_LTK_P256; | ||
1007 | |||
1008 | if (hcon->pending_sec_level == BT_SECURITY_FIPS) | ||
1009 | auth = 1; | ||
1010 | else | ||
1011 | auth = 0; | ||
1012 | |||
1013 | memset(smp->tk + smp->enc_key_size, 0, | ||
1014 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | ||
1015 | |||
1016 | smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | ||
1017 | key_type, auth, smp->tk, smp->enc_key_size, | ||
1018 | 0, 0); | ||
1019 | } | ||
1020 | |||
997 | static void sc_generate_link_key(struct smp_chan *smp) | 1021 | static void sc_generate_link_key(struct smp_chan *smp) |
998 | { | 1022 | { |
999 | /* These constants are as specified in the core specification. | 1023 | /* 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) | |||
1312 | if (!hcon->out) { | 1336 | if (!hcon->out) { |
1313 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, | 1337 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, |
1314 | sizeof(smp->prnd), smp->prnd); | 1338 | sizeof(smp->prnd), smp->prnd); |
1315 | if (smp->passkey_round == 20) { | 1339 | if (smp->passkey_round == 20) |
1316 | sc_dhkey_check(smp); | ||
1317 | SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); | 1340 | SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); |
1318 | } else { | 1341 | else |
1319 | SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); | 1342 | SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); |
1320 | } | ||
1321 | return 0; | 1343 | return 0; |
1322 | } | 1344 | } |
1323 | 1345 | ||
@@ -1394,7 +1416,14 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) | |||
1394 | return 0; | 1416 | return 0; |
1395 | } | 1417 | } |
1396 | 1418 | ||
1397 | sc_dhkey_check(smp); | 1419 | /* Initiator sends DHKey check first */ |
1420 | if (hcon->out) { | ||
1421 | sc_dhkey_check(smp); | ||
1422 | SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); | ||
1423 | } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) { | ||
1424 | sc_dhkey_check(smp); | ||
1425 | sc_add_ltk(smp); | ||
1426 | } | ||
1398 | 1427 | ||
1399 | return 0; | 1428 | return 0; |
1400 | } | 1429 | } |
@@ -2262,7 +2291,6 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) | |||
2262 | struct smp_chan *smp = chan->data; | 2291 | struct smp_chan *smp = chan->data; |
2263 | u8 a[7], b[7], *local_addr, *remote_addr; | 2292 | u8 a[7], b[7], *local_addr, *remote_addr; |
2264 | u8 io_cap[3], r[16], e[16]; | 2293 | u8 io_cap[3], r[16], e[16]; |
2265 | u8 key_type, auth; | ||
2266 | int err; | 2294 | int err; |
2267 | 2295 | ||
2268 | BT_DBG("conn %p", conn); | 2296 | BT_DBG("conn %p", conn); |
@@ -2298,19 +2326,17 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) | |||
2298 | if (memcmp(check->e, e, 16)) | 2326 | if (memcmp(check->e, e, 16)) |
2299 | return SMP_DHKEY_CHECK_FAILED; | 2327 | return SMP_DHKEY_CHECK_FAILED; |
2300 | 2328 | ||
2301 | if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags)) | 2329 | if (!hcon->out) { |
2302 | key_type = SMP_LTK_P256_DEBUG; | 2330 | if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) { |
2303 | else | 2331 | set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags); |
2304 | key_type = SMP_LTK_P256; | 2332 | return 0; |
2333 | } | ||
2305 | 2334 | ||
2306 | if (hcon->pending_sec_level == BT_SECURITY_FIPS) | 2335 | /* Slave sends DHKey check as response to master */ |
2307 | auth = 1; | 2336 | sc_dhkey_check(smp); |
2308 | else | 2337 | } |
2309 | auth = 0; | ||
2310 | 2338 | ||
2311 | smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | 2339 | sc_add_ltk(smp); |
2312 | key_type, auth, smp->tk, smp->enc_key_size, | ||
2313 | 0, 0); | ||
2314 | 2340 | ||
2315 | if (hcon->out) { | 2341 | if (hcon->out) { |
2316 | hci_le_start_enc(hcon, 0, 0, smp->tk); | 2342 | hci_le_start_enc(hcon, 0, 0, smp->tk); |