diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 80 |
2 files changed, 82 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2649caf4db96..7793fc644b87 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -995,6 +995,8 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering); | |||
995 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); | 995 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); |
996 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); | 996 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); |
997 | 997 | ||
998 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); | ||
999 | |||
998 | /* HCI info for socket */ | 1000 | /* HCI info for socket */ |
999 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | 1001 | #define hci_pi(sk) ((struct hci_pinfo *) sk) |
1000 | 1002 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad8986276848..fd0b08115f2e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -2191,6 +2191,60 @@ done: | |||
2191 | return err; | 2191 | return err; |
2192 | } | 2192 | } |
2193 | 2193 | ||
2194 | static int load_long_term_keys(struct sock *sk, u16 index, | ||
2195 | void *cp_data, u16 len) | ||
2196 | { | ||
2197 | struct hci_dev *hdev; | ||
2198 | struct mgmt_cp_load_long_term_keys *cp = cp_data; | ||
2199 | u16 key_count, expected_len; | ||
2200 | int i; | ||
2201 | |||
2202 | if (len < sizeof(*cp)) | ||
2203 | return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
2204 | EINVAL); | ||
2205 | |||
2206 | key_count = get_unaligned_le16(&cp->key_count); | ||
2207 | |||
2208 | expected_len = sizeof(*cp) + key_count * | ||
2209 | sizeof(struct mgmt_ltk_info); | ||
2210 | if (expected_len != len) { | ||
2211 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | ||
2212 | len, expected_len); | ||
2213 | return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
2214 | EINVAL); | ||
2215 | } | ||
2216 | |||
2217 | hdev = hci_dev_get(index); | ||
2218 | if (!hdev) | ||
2219 | return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
2220 | ENODEV); | ||
2221 | |||
2222 | BT_DBG("hci%u key_count %u", index, key_count); | ||
2223 | |||
2224 | hci_dev_lock(hdev); | ||
2225 | |||
2226 | hci_smp_ltks_clear(hdev); | ||
2227 | |||
2228 | for (i = 0; i < key_count; i++) { | ||
2229 | struct mgmt_ltk_info *key = &cp->keys[i]; | ||
2230 | u8 type; | ||
2231 | |||
2232 | if (key->master) | ||
2233 | type = HCI_SMP_LTK; | ||
2234 | else | ||
2235 | type = HCI_SMP_LTK_SLAVE; | ||
2236 | |||
2237 | hci_add_ltk(hdev, &key->addr.bdaddr, key->addr.type, | ||
2238 | type, 0, key->authenticated, key->val, | ||
2239 | key->enc_size, key->ediv, key->rand); | ||
2240 | } | ||
2241 | |||
2242 | hci_dev_unlock(hdev); | ||
2243 | hci_dev_put(hdev); | ||
2244 | |||
2245 | return 0; | ||
2246 | } | ||
2247 | |||
2194 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 2248 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
2195 | { | 2249 | { |
2196 | void *buf; | 2250 | void *buf; |
@@ -2325,6 +2379,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2325 | case MGMT_OP_UNBLOCK_DEVICE: | 2379 | case MGMT_OP_UNBLOCK_DEVICE: |
2326 | err = unblock_device(sk, index, cp, len); | 2380 | err = unblock_device(sk, index, cp, len); |
2327 | break; | 2381 | break; |
2382 | case MGMT_OP_LOAD_LONG_TERM_KEYS: | ||
2383 | err = load_long_term_keys(sk, index, cp, len); | ||
2384 | break; | ||
2328 | default: | 2385 | default: |
2329 | BT_DBG("Unknown op %u", opcode); | 2386 | BT_DBG("Unknown op %u", opcode); |
2330 | err = cmd_status(sk, index, opcode, | 2387 | err = cmd_status(sk, index, opcode, |
@@ -2478,6 +2535,29 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
2478 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 2535 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
2479 | } | 2536 | } |
2480 | 2537 | ||
2538 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) | ||
2539 | { | ||
2540 | struct mgmt_ev_new_long_term_key ev; | ||
2541 | |||
2542 | memset(&ev, 0, sizeof(ev)); | ||
2543 | |||
2544 | ev.store_hint = persistent; | ||
2545 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); | ||
2546 | ev.key.addr.type = key->bdaddr_type; | ||
2547 | ev.key.authenticated = key->authenticated; | ||
2548 | ev.key.enc_size = key->enc_size; | ||
2549 | ev.key.ediv = key->ediv; | ||
2550 | |||
2551 | if (key->type == HCI_SMP_LTK) | ||
2552 | ev.key.master = 1; | ||
2553 | |||
2554 | memcpy(ev.key.rand, key->rand, sizeof(key->rand)); | ||
2555 | memcpy(ev.key.val, key->val, sizeof(key->val)); | ||
2556 | |||
2557 | return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, | ||
2558 | &ev, sizeof(ev), NULL); | ||
2559 | } | ||
2560 | |||
2481 | int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 2561 | int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
2482 | u8 addr_type, u8 *name, u8 name_len, | 2562 | u8 addr_type, u8 *name, u8 name_len, |
2483 | u8 *dev_class) | 2563 | u8 *dev_class) |