aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci.h2
-rw-r--r--include/net/bluetooth/hci_core.h17
-rw-r--r--include/net/bluetooth/mgmt.h29
-rw-r--r--net/bluetooth/hci_core.c85
-rw-r--r--net/bluetooth/hci_event.c51
-rw-r--r--net/bluetooth/mgmt.c116
6 files changed, 300 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 9ce46cd00ba2..08fbf1253b83 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -82,6 +82,8 @@ enum {
82 HCI_MGMT, 82 HCI_MGMT,
83 HCI_PAIRABLE, 83 HCI_PAIRABLE,
84 HCI_SERVICE_CACHE, 84 HCI_SERVICE_CACHE,
85 HCI_LINK_KEYS,
86 HCI_DEBUG_KEYS,
85}; 87};
86 88
87/* HCI ioctl defines */ 89/* HCI ioctl defines */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e62da084e01d..009fa63a9048 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -73,6 +73,14 @@ struct bt_uuid {
73 u8 svc_hint; 73 u8 svc_hint;
74}; 74};
75 75
76struct link_key {
77 struct list_head list;
78 bdaddr_t bdaddr;
79 u8 type;
80 u8 val[16];
81 u8 pin_len;
82};
83
76#define NUM_REASSEMBLY 4 84#define NUM_REASSEMBLY 4
77struct hci_dev { 85struct hci_dev {
78 struct list_head list; 86 struct list_head list;
@@ -153,6 +161,8 @@ struct hci_dev {
153 161
154 struct list_head uuids; 162 struct list_head uuids;
155 163
164 struct list_head link_keys;
165
156 struct hci_dev_stats stat; 166 struct hci_dev_stats stat;
157 167
158 struct sk_buff_head driver_init; 168 struct sk_buff_head driver_init;
@@ -461,6 +471,12 @@ int hci_blacklist_clear(struct hci_dev *hdev);
461 471
462int hci_uuids_clear(struct hci_dev *hdev); 472int hci_uuids_clear(struct hci_dev *hdev);
463 473
474int hci_link_keys_clear(struct hci_dev *hdev);
475struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
476int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
477 u8 *key, u8 type, u8 pin_len);
478int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
479
464void hci_del_off_timer(struct hci_dev *hdev); 480void hci_del_off_timer(struct hci_dev *hdev);
465 481
466void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 482void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -697,6 +713,7 @@ int mgmt_index_removed(u16 index);
697int mgmt_powered(u16 index, u8 powered); 713int mgmt_powered(u16 index, u8 powered);
698int mgmt_discoverable(u16 index, u8 discoverable); 714int mgmt_discoverable(u16 index, u8 discoverable);
699int mgmt_connectable(u16 index, u8 connectable); 715int mgmt_connectable(u16 index, u8 connectable);
716int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type);
700 717
701/* HCI info for socket */ 718/* HCI info for socket */
702#define hci_pi(sk) ((struct hci_pinfo *) sk) 719#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index b092c4c014eb..56b500a2f68c 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -98,6 +98,28 @@ struct mgmt_cp_set_service_cache {
98 __u8 enable; 98 __u8 enable;
99} __packed; 99} __packed;
100 100
101struct mgmt_key_info {
102 bdaddr_t bdaddr;
103 u8 type;
104 u8 val[16];
105 u8 pin_len;
106} __packed;
107
108#define MGMT_OP_LOAD_KEYS 0x000D
109struct mgmt_cp_load_keys {
110 __le16 index;
111 __u8 debug_keys;
112 __le16 key_count;
113 struct mgmt_key_info keys[0];
114} __packed;
115
116#define MGMT_OP_REMOVE_KEY 0x000E
117struct mgmt_cp_remove_key {
118 __le16 index;
119 bdaddr_t bdaddr;
120 __u8 disconnect;
121} __packed;
122
101#define MGMT_EV_CMD_COMPLETE 0x0001 123#define MGMT_EV_CMD_COMPLETE 0x0001
102struct mgmt_ev_cmd_complete { 124struct mgmt_ev_cmd_complete {
103 __le16 opcode; 125 __le16 opcode;
@@ -133,3 +155,10 @@ struct mgmt_ev_index_removed {
133#define MGMT_EV_CONNECTABLE 0x0008 155#define MGMT_EV_CONNECTABLE 0x0008
134 156
135#define MGMT_EV_PAIRABLE 0x0009 157#define MGMT_EV_PAIRABLE 0x0009
158
159#define MGMT_EV_NEW_KEY 0x000A
160struct mgmt_ev_new_key {
161 __le16 index;
162 struct mgmt_key_info key;
163 __u8 old_key_type;
164} __packed;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 748f5a65caf4..8ca8cf147058 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -970,6 +970,88 @@ int hci_uuids_clear(struct hci_dev *hdev)
970 return 0; 970 return 0;
971} 971}
972 972
973int hci_link_keys_clear(struct hci_dev *hdev)
974{
975 struct list_head *p, *n;
976
977 list_for_each_safe(p, n, &hdev->link_keys) {
978 struct link_key *key;
979
980 key = list_entry(p, struct link_key, list);
981
982 list_del(p);
983 kfree(key);
984 }
985
986 return 0;
987}
988
989struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
990{
991 struct list_head *p;
992
993 list_for_each(p, &hdev->link_keys) {
994 struct link_key *k;
995
996 k = list_entry(p, struct link_key, list);
997
998 if (bacmp(bdaddr, &k->bdaddr) == 0)
999 return k;
1000 }
1001
1002 return NULL;
1003}
1004
1005int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
1006 u8 *val, u8 type, u8 pin_len)
1007{
1008 struct link_key *key, *old_key;
1009 u8 old_key_type;
1010
1011 old_key = hci_find_link_key(hdev, bdaddr);
1012 if (old_key) {
1013 old_key_type = old_key->type;
1014 key = old_key;
1015 } else {
1016 old_key_type = 0xff;
1017 key = kzalloc(sizeof(*key), GFP_ATOMIC);
1018 if (!key)
1019 return -ENOMEM;
1020 list_add(&key->list, &hdev->link_keys);
1021 }
1022
1023 BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
1024
1025 bacpy(&key->bdaddr, bdaddr);
1026 memcpy(key->val, val, 16);
1027 key->type = type;
1028 key->pin_len = pin_len;
1029
1030 if (new_key)
1031 mgmt_new_key(hdev->id, key, old_key_type);
1032
1033 if (type == 0x06)
1034 key->type = old_key_type;
1035
1036 return 0;
1037}
1038
1039int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
1040{
1041 struct link_key *key;
1042
1043 key = hci_find_link_key(hdev, bdaddr);
1044 if (!key)
1045 return -ENOENT;
1046
1047 BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
1048
1049 list_del(&key->list);
1050 kfree(key);
1051
1052 return 0;
1053}
1054
973/* Register HCI device */ 1055/* Register HCI device */
974int hci_register_dev(struct hci_dev *hdev) 1056int hci_register_dev(struct hci_dev *hdev)
975{ 1057{
@@ -1029,6 +1111,8 @@ int hci_register_dev(struct hci_dev *hdev)
1029 1111
1030 INIT_LIST_HEAD(&hdev->uuids); 1112 INIT_LIST_HEAD(&hdev->uuids);
1031 1113
1114 INIT_LIST_HEAD(&hdev->link_keys);
1115
1032 INIT_WORK(&hdev->power_on, hci_power_on); 1116 INIT_WORK(&hdev->power_on, hci_power_on);
1033 INIT_WORK(&hdev->power_off, hci_power_off); 1117 INIT_WORK(&hdev->power_off, hci_power_off);
1034 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); 1118 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1105,6 +1189,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
1105 hci_dev_lock_bh(hdev); 1189 hci_dev_lock_bh(hdev);
1106 hci_blacklist_clear(hdev); 1190 hci_blacklist_clear(hdev);
1107 hci_uuids_clear(hdev); 1191 hci_uuids_clear(hdev);
1192 hci_link_keys_clear(hdev);
1108 hci_dev_unlock_bh(hdev); 1193 hci_dev_unlock_bh(hdev);
1109 1194
1110 __hci_dev_put(hdev); 1195 __hci_dev_put(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c69ee44d5bd7..80ffd3a901fc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1810,13 +1810,60 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
1810 1810
1811static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 1811static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
1812{ 1812{
1813 struct hci_ev_link_key_req *ev = (void *) skb->data;
1814 struct hci_cp_link_key_reply cp;
1815 struct hci_conn *conn;
1816 struct link_key *key;
1817
1813 BT_DBG("%s", hdev->name); 1818 BT_DBG("%s", hdev->name);
1819
1820 if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
1821 return;
1822
1823 hci_dev_lock(hdev);
1824
1825 key = hci_find_link_key(hdev, &ev->bdaddr);
1826 if (!key) {
1827 BT_DBG("%s link key not found for %s", hdev->name,
1828 batostr(&ev->bdaddr));
1829 goto not_found;
1830 }
1831
1832 BT_DBG("%s found key type %u for %s", hdev->name, key->type,
1833 batostr(&ev->bdaddr));
1834
1835 if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
1836 BT_DBG("%s ignoring debug key", hdev->name);
1837 goto not_found;
1838 }
1839
1840 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1841
1842 if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
1843 (conn->auth_type & 0x01)) {
1844 BT_DBG("%s ignoring unauthenticated key", hdev->name);
1845 goto not_found;
1846 }
1847
1848 bacpy(&cp.bdaddr, &ev->bdaddr);
1849 memcpy(cp.link_key, key->val, 16);
1850
1851 hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
1852
1853 hci_dev_unlock(hdev);
1854
1855 return;
1856
1857not_found:
1858 hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
1859 hci_dev_unlock(hdev);
1814} 1860}
1815 1861
1816static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 1862static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
1817{ 1863{
1818 struct hci_ev_link_key_notify *ev = (void *) skb->data; 1864 struct hci_ev_link_key_notify *ev = (void *) skb->data;
1819 struct hci_conn *conn; 1865 struct hci_conn *conn;
1866 u8 pin_len = 0;
1820 1867
1821 BT_DBG("%s", hdev->name); 1868 BT_DBG("%s", hdev->name);
1822 1869
@@ -1829,6 +1876,10 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
1829 hci_conn_put(conn); 1876 hci_conn_put(conn);
1830 } 1877 }
1831 1878
1879 if (test_bit(HCI_LINK_KEYS, &hdev->flags))
1880 hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
1881 ev->key_type, pin_len);
1882
1832 hci_dev_unlock(hdev); 1883 hci_dev_unlock(hdev);
1833} 1884}
1834 1885
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a08f4ce03182..bdb0e85f182e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -794,6 +794,99 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
794 return err; 794 return err;
795} 795}
796 796
797static int load_keys(struct sock *sk, unsigned char *data, u16 len)
798{
799 struct hci_dev *hdev;
800 struct mgmt_cp_load_keys *cp;
801 u16 dev_id, key_count, expected_len;
802 int i;
803
804 cp = (void *) data;
805 dev_id = get_unaligned_le16(&cp->index);
806 key_count = get_unaligned_le16(&cp->key_count);
807
808 expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
809 if (expected_len != len) {
810 BT_ERR("load_keys: expected %u bytes, got %u bytes",
811 len, expected_len);
812 return -EINVAL;
813 }
814
815 hdev = hci_dev_get(dev_id);
816 if (!hdev)
817 return cmd_status(sk, MGMT_OP_LOAD_KEYS, ENODEV);
818
819 BT_DBG("hci%u debug_keys %u key_count %u", dev_id, cp->debug_keys,
820 key_count);
821
822 hci_dev_lock_bh(hdev);
823
824 hci_link_keys_clear(hdev);
825
826 set_bit(HCI_LINK_KEYS, &hdev->flags);
827
828 if (cp->debug_keys)
829 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
830 else
831 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
832
833 for (i = 0; i < key_count; i++) {
834 struct mgmt_key_info *key = &cp->keys[i];
835
836 hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
837 key->pin_len);
838 }
839
840 hci_dev_unlock_bh(hdev);
841 hci_dev_put(hdev);
842
843 return 0;
844}
845
846static int remove_key(struct sock *sk, unsigned char *data, u16 len)
847{
848 struct hci_dev *hdev;
849 struct mgmt_cp_remove_key *cp;
850 struct hci_conn *conn;
851 u16 dev_id;
852 int err;
853
854 cp = (void *) data;
855 dev_id = get_unaligned_le16(&cp->index);
856
857 hdev = hci_dev_get(dev_id);
858 if (!hdev)
859 return cmd_status(sk, MGMT_OP_REMOVE_KEY, ENODEV);
860
861 hci_dev_lock_bh(hdev);
862
863 err = hci_remove_link_key(hdev, &cp->bdaddr);
864 if (err < 0) {
865 err = cmd_status(sk, MGMT_OP_REMOVE_KEY, -err);
866 goto unlock;
867 }
868
869 err = 0;
870
871 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
872 goto unlock;
873
874 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
875 if (conn) {
876 struct hci_cp_disconnect dc;
877
878 put_unaligned_le16(conn->handle, &dc.handle);
879 dc.reason = 0x13; /* Remote User Terminated Connection */
880 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
881 }
882
883unlock:
884 hci_dev_unlock_bh(hdev);
885 hci_dev_put(hdev);
886
887 return err;
888}
889
797int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 890int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
798{ 891{
799 unsigned char *buf; 892 unsigned char *buf;
@@ -858,6 +951,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
858 case MGMT_OP_SET_SERVICE_CACHE: 951 case MGMT_OP_SET_SERVICE_CACHE:
859 err = set_service_cache(sk, buf + sizeof(*hdr), len); 952 err = set_service_cache(sk, buf + sizeof(*hdr), len);
860 break; 953 break;
954 case MGMT_OP_LOAD_KEYS:
955 err = load_keys(sk, buf + sizeof(*hdr), len);
956 break;
957 case MGMT_OP_REMOVE_KEY:
958 err = remove_key(sk, buf + sizeof(*hdr), len);
959 break;
861 default: 960 default:
862 BT_DBG("Unknown op %u", opcode); 961 BT_DBG("Unknown op %u", opcode);
863 err = cmd_status(sk, opcode, 0x01); 962 err = cmd_status(sk, opcode, 0x01);
@@ -974,3 +1073,20 @@ int mgmt_connectable(u16 index, u8 connectable)
974 1073
975 return ret; 1074 return ret;
976} 1075}
1076
1077int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
1078{
1079 struct mgmt_ev_new_key ev;
1080
1081 memset(&ev, 0, sizeof(ev));
1082
1083 put_unaligned_le16(index, &ev.index);
1084
1085 bacpy(&ev.key.bdaddr, &key->bdaddr);
1086 ev.key.type = key->type;
1087 memcpy(ev.key.val, key->val, 16);
1088 ev.key.pin_len = key->pin_len;
1089 ev.old_key_type = old_key_type;
1090
1091 return mgmt_event(MGMT_EV_NEW_KEY, &ev, sizeof(ev), NULL);
1092}