aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/smp.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-06-25 04:10:28 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-12-03 10:51:19 -0500
commit38606f1418cc9c0ac4230f4d9133a2cae5e02416 (patch)
tree06e1a973c8e315cfdbb48486635c2e0a43b5271a /net/bluetooth/smp.c
parente3befab970a0230a80f7732fd59bc19df26f805f (diff)
Bluetooth: Add passkey entry support for LE SC
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> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r--net/bluetooth/smp.c191
1 files changed, 180 insertions, 11 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a322019610eb..8cfa1c1b205c 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -55,6 +55,7 @@ enum {
55 SMP_FLAG_SC, 55 SMP_FLAG_SC,
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}; 59};
59 60
60struct smp_chan { 61struct smp_chan {
@@ -81,6 +82,7 @@ struct smp_chan {
81 u8 *link_key; 82 u8 *link_key;
82 unsigned long flags; 83 unsigned long flags;
83 u8 method; 84 u8 method;
85 u8 passkey_round;
84 86
85 /* Secure Connections variables */ 87 /* Secure Connections variables */
86 u8 local_pk[64]; 88 u8 local_pk[64];
@@ -1219,7 +1221,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
1219 return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk); 1221 return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
1220} 1222}
1221 1223
1222static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey) 1224static void sc_dhkey_check(struct smp_chan *smp)
1223{ 1225{
1224 struct hci_conn *hcon = smp->conn->hcon; 1226 struct hci_conn *hcon = smp->conn->hcon;
1225 struct smp_cmd_dhkey_check check; 1227 struct smp_cmd_dhkey_check check;
@@ -1244,7 +1246,7 @@ static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
1244 memset(r, 0, sizeof(r)); 1246 memset(r, 0, sizeof(r));
1245 1247
1246 if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) 1248 if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
1247 memcpy(r, &passkey, sizeof(passkey)); 1249 put_unaligned_le32(hcon->passkey_notify, r);
1248 1250
1249 smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap, 1251 smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
1250 local_addr, remote_addr, check.e); 1252 local_addr, remote_addr, check.e);
@@ -1252,8 +1254,124 @@ static void sc_dhkey_check(struct smp_chan *smp, __le32 passkey)
1252 smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check); 1254 smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
1253} 1255}
1254 1256
1257static u8 sc_passkey_send_confirm(struct smp_chan *smp)
1258{
1259 struct l2cap_conn *conn = smp->conn;
1260 struct hci_conn *hcon = conn->hcon;
1261 struct smp_cmd_pairing_confirm cfm;
1262 u8 r;
1263
1264 r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
1265 r |= 0x80;
1266
1267 get_random_bytes(smp->prnd, sizeof(smp->prnd));
1268
1269 if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r,
1270 cfm.confirm_val))
1271 return SMP_UNSPECIFIED;
1272
1273 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
1274
1275 return 0;
1276}
1277
1278static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
1279{
1280 struct l2cap_conn *conn = smp->conn;
1281 struct hci_conn *hcon = conn->hcon;
1282 struct hci_dev *hdev = hcon->hdev;
1283 u8 cfm[16], r;
1284
1285 /* Ignore the PDU if we've already done 20 rounds (0 - 19) */
1286 if (smp->passkey_round >= 20)
1287 return 0;
1288
1289 switch (smp_op) {
1290 case SMP_CMD_PAIRING_RANDOM:
1291 r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
1292 r |= 0x80;
1293
1294 if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
1295 smp->rrnd, r, cfm))
1296 return SMP_UNSPECIFIED;
1297
1298 if (memcmp(smp->pcnf, cfm, 16))
1299 return SMP_CONFIRM_FAILED;
1300
1301 smp->passkey_round++;
1302
1303 if (smp->passkey_round == 20) {
1304 /* Generate MacKey and LTK */
1305 if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk))
1306 return SMP_UNSPECIFIED;
1307 }
1308
1309 /* The round is only complete when the initiator
1310 * receives pairing random.
1311 */
1312 if (!hcon->out) {
1313 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
1314 sizeof(smp->prnd), smp->prnd);
1315 if (smp->passkey_round == 20) {
1316 sc_dhkey_check(smp);
1317 SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
1318 } else {
1319 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
1320 }
1321 return 0;
1322 }
1323
1324 /* Start the next round */
1325 if (smp->passkey_round != 20)
1326 return sc_passkey_round(smp, 0);
1327
1328 /* Passkey rounds are complete - start DHKey Check */
1329 sc_dhkey_check(smp);
1330 SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
1331
1332 break;
1333
1334 case SMP_CMD_PAIRING_CONFIRM:
1335 if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
1336 set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
1337 return 0;
1338 }
1339
1340 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
1341
1342 if (hcon->out) {
1343 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
1344 sizeof(smp->prnd), smp->prnd);
1345 return 0;
1346 }
1347
1348 return sc_passkey_send_confirm(smp);
1349
1350 case SMP_CMD_PUBLIC_KEY:
1351 default:
1352 /* Initiating device starts the round */
1353 if (!hcon->out)
1354 return 0;
1355
1356 BT_DBG("%s Starting passkey round %u", hdev->name,
1357 smp->passkey_round + 1);
1358
1359 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
1360
1361 return sc_passkey_send_confirm(smp);
1362 }
1363
1364 return 0;
1365}
1366
1255static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) 1367static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
1256{ 1368{
1369 struct l2cap_conn *conn = smp->conn;
1370 struct hci_conn *hcon = conn->hcon;
1371 u8 smp_op;
1372
1373 clear_bit(SMP_FLAG_WAIT_USER, &smp->flags);
1374
1257 switch (mgmt_op) { 1375 switch (mgmt_op) {
1258 case MGMT_OP_USER_PASSKEY_NEG_REPLY: 1376 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
1259 smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED); 1377 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)
1261 case MGMT_OP_USER_CONFIRM_NEG_REPLY: 1379 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
1262 smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED); 1380 smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
1263 return 0; 1381 return 0;
1382 case MGMT_OP_USER_PASSKEY_REPLY:
1383 hcon->passkey_notify = le32_to_cpu(passkey);
1384 smp->passkey_round = 0;
1385
1386 if (test_and_clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags))
1387 smp_op = SMP_CMD_PAIRING_CONFIRM;
1388 else
1389 smp_op = 0;
1390
1391 if (sc_passkey_round(smp, smp_op))
1392 return -EIO;
1393
1394 return 0;
1264 } 1395 }
1265 1396
1266 sc_dhkey_check(smp, passkey); 1397 sc_dhkey_check(smp);
1267 1398
1268 return 0; 1399 return 0;
1269} 1400}
@@ -1532,6 +1663,9 @@ static u8 sc_check_confirm(struct smp_chan *smp)
1532 if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags)) 1663 if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
1533 return SMP_UNSPECIFIED; 1664 return SMP_UNSPECIFIED;
1534 1665
1666 if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
1667 return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
1668
1535 if (conn->hcon->out) { 1669 if (conn->hcon->out) {
1536 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), 1670 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
1537 smp->prnd); 1671 smp->prnd);
@@ -1592,6 +1726,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
1592 if (!test_bit(SMP_FLAG_SC, &smp->flags)) 1726 if (!test_bit(SMP_FLAG_SC, &smp->flags))
1593 return smp_random(smp); 1727 return smp_random(smp);
1594 1728
1729 /* Passkey entry has special treatment */
1730 if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
1731 return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
1732
1595 if (hcon->out) { 1733 if (hcon->out) {
1596 u8 cfm[16]; 1734 u8 cfm[16];
1597 1735
@@ -1623,24 +1761,25 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
1623 if (err) 1761 if (err)
1624 return SMP_UNSPECIFIED; 1762 return SMP_UNSPECIFIED;
1625 1763
1626 err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
1627 if (err)
1628 return SMP_UNSPECIFIED;
1629
1630 if (smp->method == JUST_WORKS) { 1764 if (smp->method == JUST_WORKS) {
1631 if (hcon->out) { 1765 if (hcon->out) {
1632 sc_dhkey_check(smp, passkey); 1766 sc_dhkey_check(smp);
1633 SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 1767 SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
1634 } 1768 }
1635 return 0; 1769 return 0;
1636 } 1770 }
1637 1771
1638 err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, 1772 err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
1639 hcon->type, hcon->dst_type, 1773 if (err)
1640 passkey, 0); 1774 return SMP_UNSPECIFIED;
1775
1776 err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type,
1777 hcon->dst_type, passkey, 0);
1641 if (err) 1778 if (err)
1642 return SMP_UNSPECIFIED; 1779 return SMP_UNSPECIFIED;
1643 1780
1781 set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
1782
1644 return 0; 1783 return 0;
1645} 1784}
1646 1785
@@ -2071,6 +2210,33 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
2071 if (!memcmp(debug_pk, smp->remote_pk, 64)) 2210 if (!memcmp(debug_pk, smp->remote_pk, 64))
2072 set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); 2211 set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
2073 2212
2213 if (smp->method == DSP_PASSKEY) {
2214 get_random_bytes(&hcon->passkey_notify,
2215 sizeof(hcon->passkey_notify));
2216 hcon->passkey_notify %= 1000000;
2217 hcon->passkey_entered = 0;
2218 smp->passkey_round = 0;
2219 if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type,
2220 hcon->dst_type,
2221 hcon->passkey_notify,
2222 hcon->passkey_entered))
2223 return SMP_UNSPECIFIED;
2224 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
2225 return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
2226 }
2227
2228 if (hcon->out)
2229 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
2230
2231 if (smp->method == REQ_PASSKEY) {
2232 if (mgmt_user_passkey_request(hdev, &hcon->dst, hcon->type,
2233 hcon->dst_type))
2234 return SMP_UNSPECIFIED;
2235 SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
2236 set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
2237 return 0;
2238 }
2239
2074 /* The Initiating device waits for the non-initiating device to 2240 /* The Initiating device waits for the non-initiating device to
2075 * send the confirm value. 2241 * send the confirm value.
2076 */ 2242 */
@@ -2121,6 +2287,9 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
2121 2287
2122 memset(r, 0, sizeof(r)); 2288 memset(r, 0, sizeof(r));
2123 2289
2290 if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
2291 put_unaligned_le32(hcon->passkey_notify, r);
2292
2124 err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r, 2293 err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
2125 io_cap, remote_addr, local_addr, e); 2294 io_cap, remote_addr, local_addr, e);
2126 if (err) 2295 if (err)