blob: fa22f4aa3b04c0c7952abe096a2fe7fd2bea8dcc [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
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>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030027#include <linux/crypto.h>
28#include <crypto/b128ops.h>
29
30static inline void swap128(u8 src[16], u8 dst[16])
31{
32 int i;
33 for (i = 0; i < 16; i++)
34 dst[15 - i] = src[i];
35}
36
37static inline void swap56(u8 src[7], u8 dst[7])
38{
39 int i;
40 for (i = 0; i < 7; i++)
41 dst[6 - i] = src[i];
42}
43
44static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
45{
46 struct blkcipher_desc desc;
47 struct scatterlist sg;
48 int err, iv_len;
49 unsigned char iv[128];
50
51 if (tfm == NULL) {
52 BT_ERR("tfm %p", tfm);
53 return -EINVAL;
54 }
55
56 desc.tfm = tfm;
57 desc.flags = 0;
58
59 err = crypto_blkcipher_setkey(tfm, k, 16);
60 if (err) {
61 BT_ERR("cipher setkey failed: %d", err);
62 return err;
63 }
64
65 sg_init_one(&sg, r, 16);
66
67 iv_len = crypto_blkcipher_ivsize(tfm);
68 if (iv_len) {
69 memset(&iv, 0xff, iv_len);
70 crypto_blkcipher_set_iv(tfm, iv, iv_len);
71 }
72
73 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
74 if (err)
75 BT_ERR("Encrypt data error %d", err);
76
77 return err;
78}
79
80static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
81 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
82 u8 _rat, bdaddr_t *ra, u8 res[16])
83{
84 u8 p1[16], p2[16];
85 int err;
86
87 memset(p1, 0, 16);
88
89 /* p1 = pres || preq || _rat || _iat */
90 swap56(pres, p1);
91 swap56(preq, p1 + 7);
92 p1[14] = _rat;
93 p1[15] = _iat;
94
95 memset(p2, 0, 16);
96
97 /* p2 = padding || ia || ra */
98 baswap((bdaddr_t *) (p2 + 4), ia);
99 baswap((bdaddr_t *) (p2 + 10), ra);
100
101 /* res = r XOR p1 */
102 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
103
104 /* res = e(k, res) */
105 err = smp_e(tfm, k, res);
106 if (err) {
107 BT_ERR("Encrypt data error");
108 return err;
109 }
110
111 /* res = res XOR p2 */
112 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
113
114 /* res = e(k, res) */
115 err = smp_e(tfm, k, res);
116 if (err)
117 BT_ERR("Encrypt data error");
118
119 return err;
120}
121
122static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
123 u8 r1[16], u8 r2[16], u8 _r[16])
124{
125 int err;
126
127 /* Just least significant octets from r1 and r2 are considered */
128 memcpy(_r, r1 + 8, 8);
129 memcpy(_r + 8, r2 + 8, 8);
130
131 err = smp_e(tfm, k, _r);
132 if (err)
133 BT_ERR("Encrypt data error");
134
135 return err;
136}
137
138static int smp_rand(u8 *buf)
139{
140 get_random_bytes(buf, 16);
141
142 return 0;
143}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300144
145static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
146 u16 dlen, void *data)
147{
148 struct sk_buff *skb;
149 struct l2cap_hdr *lh;
150 int len;
151
152 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
153
154 if (len > conn->mtu)
155 return NULL;
156
157 skb = bt_skb_alloc(len, GFP_ATOMIC);
158 if (!skb)
159 return NULL;
160
161 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
162 lh->len = cpu_to_le16(sizeof(code) + dlen);
163 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
164
165 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
166
167 memcpy(skb_put(skb, dlen), data, dlen);
168
169 return skb;
170}
171
172static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
173{
174 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
175
176 BT_DBG("code 0x%2.2x", code);
177
178 if (!skb)
179 return;
180
181 hci_send_acl(conn->hcon, skb, 0);
182}
183
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300184static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
185{
186 struct smp_cmd_pairing *rp = (void *) skb->data;
187
188 BT_DBG("conn %p", conn);
189
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300190 conn->preq[0] = SMP_CMD_PAIRING_REQ;
191 memcpy(&conn->preq[1], rp, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300192 skb_pull(skb, sizeof(*rp));
193
194 rp->io_capability = 0x00;
195 rp->oob_flag = 0x00;
196 rp->max_key_size = 16;
197 rp->init_key_dist = 0x00;
198 rp->resp_key_dist = 0x00;
199 rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
200
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300201 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
202 memcpy(&conn->prsp[1], rp, sizeof(*rp));
203
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300204 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
205}
206
207static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
208{
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300209 struct smp_cmd_pairing *rp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300210 struct smp_cmd_pairing_confirm cp;
211
212 BT_DBG("conn %p", conn);
213
214 memset(&cp, 0, sizeof(cp));
215
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300216 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
217 memcpy(&conn->prsp[1], rp, sizeof(*rp));
218 skb_pull(skb, sizeof(*rp));
219
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300220 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
221}
222
223static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
224 struct sk_buff *skb)
225{
226 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
227
228 if (conn->hcon->out) {
229 struct smp_cmd_pairing_random random;
230
231 memset(&random, 0, sizeof(random));
232
233 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
234 &random);
235 } else {
236 struct smp_cmd_pairing_confirm confirm;
237
238 memset(&confirm, 0, sizeof(confirm));
239
240 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
241 &confirm);
242 }
243}
244
245static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
246{
247 struct smp_cmd_pairing_random cp;
248
249 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
250
251 skb_pull(skb, sizeof(cp));
252
253 if (conn->hcon->out) {
254 /* FIXME: start encryption */
255 } else {
256 memset(&cp, 0, sizeof(cp));
257
258 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
259 }
260}
261
262static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
263{
264 struct smp_cmd_security_req *rp = (void *) skb->data;
265 struct smp_cmd_pairing cp;
266
267 BT_DBG("conn %p", conn);
268
269 skb_pull(skb, sizeof(*rp));
270 memset(&cp, 0, sizeof(cp));
271
272 cp.io_capability = 0x00;
273 cp.oob_flag = 0x00;
274 cp.max_key_size = 16;
275 cp.init_key_dist = 0x00;
276 cp.resp_key_dist = 0x00;
277 cp.auth_req = rp->auth_req & (SMP_AUTH_BONDING | SMP_AUTH_MITM);
278
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300279 conn->preq[0] = SMP_CMD_PAIRING_REQ;
280 memcpy(&conn->preq[1], &cp, sizeof(cp));
281
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300282 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
283}
284
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300285int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
286{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300287 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300288 __u8 authreq;
289
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300290 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
291
292 if (IS_ERR(hcon->hdev->tfm))
293 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300294
295 switch (sec_level) {
296 case BT_SECURITY_MEDIUM:
297 /* Encrypted, no MITM protection */
298 authreq = HCI_AT_NO_BONDING_MITM;
299 break;
300
301 case BT_SECURITY_HIGH:
302 /* Bonding, MITM protection */
303 authreq = HCI_AT_GENERAL_BONDING_MITM;
304 break;
305
306 case BT_SECURITY_LOW:
307 default:
308 return 1;
309 }
310
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300311 if (hcon->link_mode & HCI_LM_MASTER) {
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300312 struct smp_cmd_pairing cp;
313 cp.io_capability = 0x00;
314 cp.oob_flag = 0x00;
315 cp.max_key_size = 16;
316 cp.init_key_dist = 0x00;
317 cp.resp_key_dist = 0x00;
318 cp.auth_req = authreq;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300319
320 conn->preq[0] = SMP_CMD_PAIRING_REQ;
321 memcpy(&conn->preq[1], &cp, sizeof(cp));
322
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300323 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
324 } else {
325 struct smp_cmd_security_req cp;
326 cp.auth_req = authreq;
327 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
328 }
329
330 return 0;
331}
332
333int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
334{
335 __u8 code = skb->data[0];
336 __u8 reason;
337 int err = 0;
338
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300339 if (IS_ERR(conn->hcon->hdev->tfm)) {
340 err = PTR_ERR(conn->hcon->hdev->tfm);
341 reason = SMP_PAIRING_NOTSUPP;
342 goto done;
343 }
344
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300345 skb_pull(skb, sizeof(code));
346
347 switch (code) {
348 case SMP_CMD_PAIRING_REQ:
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300349 smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300350 break;
351
352 case SMP_CMD_PAIRING_FAIL:
353 break;
354
355 case SMP_CMD_PAIRING_RSP:
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300356 smp_cmd_pairing_rsp(conn, skb);
357 break;
358
359 case SMP_CMD_SECURITY_REQ:
360 smp_cmd_security_req(conn, skb);
361 break;
362
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300363 case SMP_CMD_PAIRING_CONFIRM:
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300364 smp_cmd_pairing_confirm(conn, skb);
365 break;
366
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300367 case SMP_CMD_PAIRING_RANDOM:
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300368 smp_cmd_pairing_random(conn, skb);
369 break;
370
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300371 case SMP_CMD_ENCRYPT_INFO:
372 case SMP_CMD_MASTER_IDENT:
373 case SMP_CMD_IDENT_INFO:
374 case SMP_CMD_IDENT_ADDR_INFO:
375 case SMP_CMD_SIGN_INFO:
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300376 default:
377 BT_DBG("Unknown command code 0x%2.2x", code);
378
379 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300380 err = -EOPNOTSUPP;
381 goto done;
382 }
383
384done:
385 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300386 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
387 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300388
389 kfree_skb(skb);
390 return err;
391}