Bluetooth: Add simple SMP pairing negotiation
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / smp.c
1 /*
2    BlueZ - Bluetooth protocol stack for Linux
3    Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2 as
7    published by the Free Software Foundation;
8
9    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20    SOFTWARE IS DISCLAIMED.
21 */
22
23 #include <net/bluetooth/bluetooth.h>
24 #include <net/bluetooth/hci_core.h>
25 #include <net/bluetooth/l2cap.h>
26 #include <net/bluetooth/smp.h>
27
28 static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
29                                                 u16 dlen, void *data)
30 {
31         struct sk_buff *skb;
32         struct l2cap_hdr *lh;
33         int len;
34
35         len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
36
37         if (len > conn->mtu)
38                 return NULL;
39
40         skb = bt_skb_alloc(len, GFP_ATOMIC);
41         if (!skb)
42                 return NULL;
43
44         lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
45         lh->len = cpu_to_le16(sizeof(code) + dlen);
46         lh->cid = cpu_to_le16(L2CAP_CID_SMP);
47
48         memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
49
50         memcpy(skb_put(skb, dlen), data, dlen);
51
52         return skb;
53 }
54
55 static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
56 {
57         struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
58
59         BT_DBG("code 0x%2.2x", code);
60
61         if (!skb)
62                 return;
63
64         hci_send_acl(conn->hcon, skb, 0);
65 }
66
67 static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
68 {
69         struct smp_cmd_pairing *rp = (void *) skb->data;
70
71         BT_DBG("conn %p", conn);
72
73         skb_pull(skb, sizeof(*rp));
74
75         rp->io_capability = 0x00;
76         rp->oob_flag = 0x00;
77         rp->max_key_size = 16;
78         rp->init_key_dist = 0x00;
79         rp->resp_key_dist = 0x00;
80         rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
81
82         smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
83 }
84
85 static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
86 {
87         struct smp_cmd_pairing_confirm cp;
88
89         BT_DBG("conn %p", conn);
90
91         memset(&cp, 0, sizeof(cp));
92
93         smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
94 }
95
96 static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
97                                                         struct sk_buff *skb)
98 {
99         BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
100
101         if (conn->hcon->out) {
102                 struct smp_cmd_pairing_random random;
103
104                 memset(&random, 0, sizeof(random));
105
106                 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
107                                                                 &random);
108         } else {
109                 struct smp_cmd_pairing_confirm confirm;
110
111                 memset(&confirm, 0, sizeof(confirm));
112
113                 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
114                                                                 &confirm);
115         }
116 }
117
118 static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
119 {
120         struct smp_cmd_pairing_random cp;
121
122         BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
123
124         skb_pull(skb, sizeof(cp));
125
126         if (conn->hcon->out) {
127                 /* FIXME: start encryption */
128         } else {
129                 memset(&cp, 0, sizeof(cp));
130
131                 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
132         }
133 }
134
135 static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
136 {
137         struct smp_cmd_security_req *rp = (void *) skb->data;
138         struct smp_cmd_pairing cp;
139
140         BT_DBG("conn %p", conn);
141
142         skb_pull(skb, sizeof(*rp));
143         memset(&cp, 0, sizeof(cp));
144
145         cp.io_capability = 0x00;
146         cp.oob_flag = 0x00;
147         cp.max_key_size = 16;
148         cp.init_key_dist = 0x00;
149         cp.resp_key_dist = 0x00;
150         cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
151
152         smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
153 }
154
155 int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
156 {
157         __u8 authreq;
158
159         BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
160
161         switch (sec_level) {
162         case BT_SECURITY_MEDIUM:
163                 /* Encrypted, no MITM protection */
164                 authreq = HCI_AT_NO_BONDING_MITM;
165                 break;
166
167         case BT_SECURITY_HIGH:
168                 /* Bonding, MITM protection */
169                 authreq = HCI_AT_GENERAL_BONDING_MITM;
170                 break;
171
172         case BT_SECURITY_LOW:
173         default:
174                 return 1;
175         }
176
177         if (conn->hcon->link_mode & HCI_LM_MASTER) {
178                 struct smp_cmd_pairing cp;
179                 cp.io_capability = 0x00;
180                 cp.oob_flag = 0x00;
181                 cp.max_key_size = 16;
182                 cp.init_key_dist = 0x00;
183                 cp.resp_key_dist = 0x00;
184                 cp.auth_req = authreq;
185                 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
186         } else {
187                 struct smp_cmd_security_req cp;
188                 cp.auth_req = authreq;
189                 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
190         }
191
192         return 0;
193 }
194
195 int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
196 {
197         __u8 code = skb->data[0];
198         __u8 reason;
199         int err = 0;
200
201         skb_pull(skb, sizeof(code));
202
203         switch (code) {
204         case SMP_CMD_PAIRING_REQ:
205                 smp_cmd_pairing_req(conn, skb);
206                 break;
207
208         case SMP_CMD_PAIRING_FAIL:
209                 break;
210
211         case SMP_CMD_PAIRING_RSP:
212                 smp_cmd_pairing_rsp(conn, skb);
213                 break;
214
215         case SMP_CMD_SECURITY_REQ:
216                 smp_cmd_security_req(conn, skb);
217                 break;
218
219         case SMP_CMD_PAIRING_CONFIRM:
220                 smp_cmd_pairing_confirm(conn, skb);
221                 break;
222
223         case SMP_CMD_PAIRING_RANDOM:
224                 smp_cmd_pairing_random(conn, skb);
225                 break;
226
227         case SMP_CMD_ENCRYPT_INFO:
228         case SMP_CMD_MASTER_IDENT:
229         case SMP_CMD_IDENT_INFO:
230         case SMP_CMD_IDENT_ADDR_INFO:
231         case SMP_CMD_SIGN_INFO:
232         default:
233                 BT_DBG("Unknown command code 0x%2.2x", code);
234
235                 reason = SMP_CMD_NOTSUPP;
236                 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
237                                                                 &reason);
238                 err = -EOPNOTSUPP;
239         }
240
241         kfree_skb(skb);
242         return err;
243 }