diff options
author | Vinicius Costa Gomes <vinicius.gomes@openbossa.org> | 2012-02-02 19:08:01 -0500 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-02-13 10:01:33 -0500 |
commit | c9839a11c0e460a2457e7cac76650d07773e6c3b (patch) | |
tree | 053e815839a9dcc099bad50863acb63eed884857 | |
parent | b899efaf9b26cadb084752862490b4fc44bc3169 (diff) |
Bluetooth: Use the updated key structures for handling LTKs
This updates all the users of the older way, that was using the
link_keys list to store the SMP keys, to use the new way.
This includes defining new types for the keys, we have a type for each
combination of STK/LTK and Master/Slave.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 11 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 76 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 38 |
4 files changed, 71 insertions, 65 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c998176a503d..2649caf4db96 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -658,12 +658,13 @@ int hci_link_keys_clear(struct hci_dev *hdev); | |||
658 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); | 658 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); |
659 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | 659 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, |
660 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); | 660 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); |
661 | struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); | 661 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); |
662 | struct link_key *hci_find_link_key_type(struct hci_dev *hdev, | 662 | int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, |
663 | bdaddr_t *bdaddr, u8 type); | 663 | int new_key, u8 authenticated, u8 tk[16], |
664 | u8 enc_size, u16 ediv, u8 rand[8]); | ||
665 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
666 | u8 addr_type); | ||
664 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); | 667 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); |
665 | int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | ||
666 | u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); | ||
667 | int hci_smp_ltks_clear(struct hci_dev *hdev); | 668 | int hci_smp_ltks_clear(struct hci_dev *hdev); |
668 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); | 669 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); |
669 | 670 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index a28e637152fe..84b7a9e4f2f6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1222,41 +1222,35 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
1222 | return 0; | 1222 | return 0; |
1223 | } | 1223 | } |
1224 | 1224 | ||
1225 | struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) | 1225 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) |
1226 | { | 1226 | { |
1227 | struct link_key *k; | 1227 | struct smp_ltk *k; |
1228 | |||
1229 | list_for_each_entry(k, &hdev->link_keys, list) { | ||
1230 | struct key_master_id *id; | ||
1231 | 1228 | ||
1232 | if (k->type != HCI_LK_SMP_LTK) | 1229 | list_for_each_entry(k, &hdev->long_term_keys, list) { |
1230 | if (k->ediv != ediv || | ||
1231 | memcmp(rand, k->rand, sizeof(k->rand))) | ||
1233 | continue; | 1232 | continue; |
1234 | 1233 | ||
1235 | if (k->dlen != sizeof(*id)) | 1234 | return k; |
1236 | continue; | ||
1237 | |||
1238 | id = (void *) &k->data; | ||
1239 | if (id->ediv == ediv && | ||
1240 | (memcmp(rand, id->rand, sizeof(id->rand)) == 0)) | ||
1241 | return k; | ||
1242 | } | 1235 | } |
1243 | 1236 | ||
1244 | return NULL; | 1237 | return NULL; |
1245 | } | 1238 | } |
1246 | EXPORT_SYMBOL(hci_find_ltk); | 1239 | EXPORT_SYMBOL(hci_find_ltk); |
1247 | 1240 | ||
1248 | struct link_key *hci_find_link_key_type(struct hci_dev *hdev, | 1241 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1249 | bdaddr_t *bdaddr, u8 type) | 1242 | u8 addr_type) |
1250 | { | 1243 | { |
1251 | struct link_key *k; | 1244 | struct smp_ltk *k; |
1252 | 1245 | ||
1253 | list_for_each_entry(k, &hdev->link_keys, list) | 1246 | list_for_each_entry(k, &hdev->long_term_keys, list) |
1254 | if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0) | 1247 | if (addr_type == k->bdaddr_type && |
1248 | bacmp(bdaddr, &k->bdaddr) == 0) | ||
1255 | return k; | 1249 | return k; |
1256 | 1250 | ||
1257 | return NULL; | 1251 | return NULL; |
1258 | } | 1252 | } |
1259 | EXPORT_SYMBOL(hci_find_link_key_type); | 1253 | EXPORT_SYMBOL(hci_find_ltk_by_addr); |
1260 | 1254 | ||
1261 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | 1255 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, |
1262 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | 1256 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) |
@@ -1313,40 +1307,36 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
1313 | return 0; | 1307 | return 0; |
1314 | } | 1308 | } |
1315 | 1309 | ||
1316 | int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | 1310 | int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, |
1317 | u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]) | 1311 | int new_key, u8 authenticated, u8 tk[16], |
1312 | u8 enc_size, u16 ediv, u8 rand[8]) | ||
1318 | { | 1313 | { |
1319 | struct link_key *key, *old_key; | 1314 | struct smp_ltk *key, *old_key; |
1320 | struct key_master_id *id; | ||
1321 | u8 old_key_type; | ||
1322 | 1315 | ||
1323 | BT_DBG("%s addr %s", hdev->name, batostr(bdaddr)); | 1316 | if (!(type & HCI_SMP_STK) && !(type & HCI_SMP_LTK)) |
1317 | return 0; | ||
1324 | 1318 | ||
1325 | old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK); | 1319 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type); |
1326 | if (old_key) { | 1320 | if (old_key) |
1327 | key = old_key; | 1321 | key = old_key; |
1328 | old_key_type = old_key->type; | 1322 | else { |
1329 | } else { | 1323 | key = kzalloc(sizeof(*key), GFP_ATOMIC); |
1330 | key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC); | ||
1331 | if (!key) | 1324 | if (!key) |
1332 | return -ENOMEM; | 1325 | return -ENOMEM; |
1333 | list_add(&key->list, &hdev->link_keys); | 1326 | list_add(&key->list, &hdev->long_term_keys); |
1334 | old_key_type = 0xff; | ||
1335 | } | 1327 | } |
1336 | 1328 | ||
1337 | key->dlen = sizeof(*id); | ||
1338 | |||
1339 | bacpy(&key->bdaddr, bdaddr); | 1329 | bacpy(&key->bdaddr, bdaddr); |
1340 | memcpy(key->val, ltk, sizeof(key->val)); | 1330 | key->bdaddr_type = addr_type; |
1341 | key->type = HCI_LK_SMP_LTK; | 1331 | memcpy(key->val, tk, sizeof(key->val)); |
1342 | key->pin_len = key_size; | 1332 | key->authenticated = authenticated; |
1343 | 1333 | key->ediv = ediv; | |
1344 | id = (void *) &key->data; | 1334 | key->enc_size = enc_size; |
1345 | id->ediv = ediv; | 1335 | key->type = type; |
1346 | memcpy(id->rand, rand, sizeof(id->rand)); | 1336 | memcpy(key->rand, rand, sizeof(key->rand)); |
1347 | 1337 | ||
1348 | if (new_key) | 1338 | if (!new_key) |
1349 | mgmt_new_link_key(hdev, key, old_key_type); | 1339 | return 0; |
1350 | 1340 | ||
1351 | return 0; | 1341 | return 0; |
1352 | } | 1342 | } |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a86f82b11316..23dbb31f0423 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -3256,7 +3256,7 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, | |||
3256 | struct hci_cp_le_ltk_reply cp; | 3256 | struct hci_cp_le_ltk_reply cp; |
3257 | struct hci_cp_le_ltk_neg_reply neg; | 3257 | struct hci_cp_le_ltk_neg_reply neg; |
3258 | struct hci_conn *conn; | 3258 | struct hci_conn *conn; |
3259 | struct link_key *ltk; | 3259 | struct smp_ltk *ltk; |
3260 | 3260 | ||
3261 | BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); | 3261 | BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); |
3262 | 3262 | ||
@@ -3272,10 +3272,17 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, | |||
3272 | 3272 | ||
3273 | memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); | 3273 | memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); |
3274 | cp.handle = cpu_to_le16(conn->handle); | 3274 | cp.handle = cpu_to_le16(conn->handle); |
3275 | conn->pin_length = ltk->pin_len; | 3275 | |
3276 | if (ltk->authenticated) | ||
3277 | conn->sec_level = BT_SECURITY_HIGH; | ||
3276 | 3278 | ||
3277 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); | 3279 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); |
3278 | 3280 | ||
3281 | if (ltk->type & HCI_SMP_STK) { | ||
3282 | list_del(<k->list); | ||
3283 | kfree(ltk); | ||
3284 | } | ||
3285 | |||
3279 | hci_dev_unlock(hdev); | 3286 | hci_dev_unlock(hdev); |
3280 | 3287 | ||
3281 | return; | 3288 | return; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 9ff56e18d99b..0563f737779a 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -475,8 +475,9 @@ static void random_work(struct work_struct *work) | |||
475 | memset(stk + smp->enc_key_size, 0, | 475 | memset(stk + smp->enc_key_size, 0, |
476 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 476 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
477 | 477 | ||
478 | hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size, | 478 | hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, |
479 | ediv, rand, stk); | 479 | HCI_SMP_STK_SLAVE, 0, 0, stk, |
480 | smp->enc_key_size, ediv, rand); | ||
480 | } | 481 | } |
481 | 482 | ||
482 | return; | 483 | return; |
@@ -701,22 +702,18 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
701 | 702 | ||
702 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn) | 703 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn) |
703 | { | 704 | { |
704 | struct link_key *key; | 705 | struct smp_ltk *key; |
705 | struct key_master_id *master; | ||
706 | struct hci_conn *hcon = conn->hcon; | 706 | struct hci_conn *hcon = conn->hcon; |
707 | 707 | ||
708 | key = hci_find_link_key_type(hcon->hdev, conn->dst, | 708 | key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); |
709 | HCI_LK_SMP_LTK); | ||
710 | if (!key) | 709 | if (!key) |
711 | return 0; | 710 | return 0; |
712 | 711 | ||
713 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) | 712 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) |
714 | return 1; | 713 | return 1; |
715 | 714 | ||
716 | master = (void *) key->data; | 715 | hci_le_start_enc(hcon, key->ediv, key->rand, key->val); |
717 | hci_le_start_enc(hcon, master->ediv, master->rand, | 716 | hcon->enc_key_size = key->enc_size; |
718 | key->val); | ||
719 | hcon->enc_key_size = key->pin_len; | ||
720 | 717 | ||
721 | return 1; | 718 | return 1; |
722 | 719 | ||
@@ -819,13 +816,19 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | |||
819 | { | 816 | { |
820 | struct smp_cmd_master_ident *rp = (void *) skb->data; | 817 | struct smp_cmd_master_ident *rp = (void *) skb->data; |
821 | struct smp_chan *smp = conn->smp_chan; | 818 | struct smp_chan *smp = conn->smp_chan; |
819 | struct hci_dev *hdev = conn->hcon->hdev; | ||
820 | struct hci_conn *hcon = conn->hcon; | ||
821 | u8 authenticated; | ||
822 | 822 | ||
823 | skb_pull(skb, sizeof(*rp)); | 823 | skb_pull(skb, sizeof(*rp)); |
824 | 824 | ||
825 | hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size, | 825 | hci_dev_lock(hdev); |
826 | rp->ediv, rp->rand, smp->tk); | 826 | authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); |
827 | 827 | hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, | |
828 | HCI_SMP_LTK, 1, authenticated, smp->tk, | ||
829 | smp->enc_key_size, rp->ediv, rp->rand); | ||
828 | smp_distribute_keys(conn, 1); | 830 | smp_distribute_keys(conn, 1); |
831 | hci_dev_unlock(hdev); | ||
829 | 832 | ||
830 | return 0; | 833 | return 0; |
831 | } | 834 | } |
@@ -935,6 +938,8 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
935 | if (*keydist & SMP_DIST_ENC_KEY) { | 938 | if (*keydist & SMP_DIST_ENC_KEY) { |
936 | struct smp_cmd_encrypt_info enc; | 939 | struct smp_cmd_encrypt_info enc; |
937 | struct smp_cmd_master_ident ident; | 940 | struct smp_cmd_master_ident ident; |
941 | struct hci_conn *hcon = conn->hcon; | ||
942 | u8 authenticated; | ||
938 | __le16 ediv; | 943 | __le16 ediv; |
939 | 944 | ||
940 | get_random_bytes(enc.ltk, sizeof(enc.ltk)); | 945 | get_random_bytes(enc.ltk, sizeof(enc.ltk)); |
@@ -943,8 +948,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
943 | 948 | ||
944 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); | 949 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); |
945 | 950 | ||
946 | hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size, | 951 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; |
947 | ediv, ident.rand, enc.ltk); | 952 | hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, |
953 | HCI_SMP_LTK_SLAVE, 1, authenticated, | ||
954 | enc.ltk, smp->enc_key_size, | ||
955 | ediv, ident.rand); | ||
948 | 956 | ||
949 | ident.ediv = cpu_to_le16(ediv); | 957 | ident.ediv = cpu_to_le16(ediv); |
950 | 958 | ||