diff options
author | Brian Gix <bgix@codeaurora.org> | 2011-11-23 11:28:33 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-01 08:51:53 -0500 |
commit | 604086b73b9b342414a53c0f34dd23aecb005ff8 (patch) | |
tree | d378965d8c019f52f957e4dffb00e17cf36ea7ed /net | |
parent | badaaa00f2122bab4bc2d46c26d6fad6af50f97c (diff) |
Bluetooth: Add User Passkey Response handling
For some MITM protection pairing scenarios, the user is
required to enter or accept a 6 digit passkey.
Signed-off-by: Brian Gix <bgix@codeaurora.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/mgmt.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c06a05c09a95..7a23f211d602 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1618,7 +1618,15 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, | |||
1618 | } | 1618 | } |
1619 | 1619 | ||
1620 | /* Continue with pairing via HCI */ | 1620 | /* Continue with pairing via HCI */ |
1621 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | 1621 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { |
1622 | struct hci_cp_user_passkey_reply cp; | ||
1623 | |||
1624 | bacpy(&cp.bdaddr, bdaddr); | ||
1625 | cp.passkey = passkey; | ||
1626 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); | ||
1627 | } else | ||
1628 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | ||
1629 | |||
1622 | if (err < 0) | 1630 | if (err < 0) |
1623 | mgmt_pending_remove(cmd); | 1631 | mgmt_pending_remove(cmd); |
1624 | 1632 | ||
@@ -1660,6 +1668,37 @@ static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data, | |||
1660 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | 1668 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); |
1661 | } | 1669 | } |
1662 | 1670 | ||
1671 | static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len) | ||
1672 | { | ||
1673 | struct mgmt_cp_user_passkey_reply *cp = (void *) data; | ||
1674 | |||
1675 | BT_DBG(""); | ||
1676 | |||
1677 | if (len != sizeof(*cp)) | ||
1678 | return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY, | ||
1679 | EINVAL); | ||
1680 | |||
1681 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1682 | MGMT_OP_USER_PASSKEY_REPLY, | ||
1683 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); | ||
1684 | } | ||
1685 | |||
1686 | static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data, | ||
1687 | u16 len) | ||
1688 | { | ||
1689 | struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data; | ||
1690 | |||
1691 | BT_DBG(""); | ||
1692 | |||
1693 | if (len != sizeof(*cp)) | ||
1694 | return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY, | ||
1695 | EINVAL); | ||
1696 | |||
1697 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1698 | MGMT_OP_USER_PASSKEY_NEG_REPLY, | ||
1699 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | ||
1700 | } | ||
1701 | |||
1663 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | 1702 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, |
1664 | u16 len) | 1703 | u16 len) |
1665 | { | 1704 | { |
@@ -2117,6 +2156,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2117 | err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), | 2156 | err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), |
2118 | len); | 2157 | len); |
2119 | break; | 2158 | break; |
2159 | case MGMT_OP_USER_PASSKEY_REPLY: | ||
2160 | err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len); | ||
2161 | break; | ||
2162 | case MGMT_OP_USER_PASSKEY_NEG_REPLY: | ||
2163 | err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr), | ||
2164 | len); | ||
2165 | break; | ||
2120 | case MGMT_OP_SET_LOCAL_NAME: | 2166 | case MGMT_OP_SET_LOCAL_NAME: |
2121 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | 2167 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); |
2122 | break; | 2168 | break; |
@@ -2477,6 +2523,18 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2477 | NULL); | 2523 | NULL); |
2478 | } | 2524 | } |
2479 | 2525 | ||
2526 | int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr) | ||
2527 | { | ||
2528 | struct mgmt_ev_user_passkey_request ev; | ||
2529 | |||
2530 | BT_DBG("%s", hdev->name); | ||
2531 | |||
2532 | bacpy(&ev.bdaddr, bdaddr); | ||
2533 | |||
2534 | return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev), | ||
2535 | NULL); | ||
2536 | } | ||
2537 | |||
2480 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2538 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2481 | u8 status, u8 opcode) | 2539 | u8 status, u8 opcode) |
2482 | { | 2540 | { |
@@ -2511,6 +2569,20 @@ int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, | |||
2511 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | 2569 | MGMT_OP_USER_CONFIRM_NEG_REPLY); |
2512 | } | 2570 | } |
2513 | 2571 | ||
2572 | int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
2573 | u8 status) | ||
2574 | { | ||
2575 | return user_pairing_resp_complete(hdev, bdaddr, status, | ||
2576 | MGMT_OP_USER_PASSKEY_REPLY); | ||
2577 | } | ||
2578 | |||
2579 | int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, | ||
2580 | bdaddr_t *bdaddr, u8 status) | ||
2581 | { | ||
2582 | return user_pairing_resp_complete(hdev, bdaddr, status, | ||
2583 | MGMT_OP_USER_PASSKEY_NEG_REPLY); | ||
2584 | } | ||
2585 | |||
2514 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) | 2586 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) |
2515 | { | 2587 | { |
2516 | struct mgmt_ev_auth_failed ev; | 2588 | struct mgmt_ev_auth_failed ev; |