blob: f0c67f62a08e36c149b5f8ab4f5533c9ab3a0b95 [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>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100028#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030029#include <crypto/b128ops.h>
30
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030031#define SMP_TIMEOUT 30000 /* 30 seconds */
32
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033static inline void swap128(u8 src[16], u8 dst[16])
34{
35 int i;
36 for (i = 0; i < 16; i++)
37 dst[15 - i] = src[i];
38}
39
40static inline void swap56(u8 src[7], u8 dst[7])
41{
42 int i;
43 for (i = 0; i < 7; i++)
44 dst[6 - i] = src[i];
45}
46
47static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
48{
49 struct blkcipher_desc desc;
50 struct scatterlist sg;
51 int err, iv_len;
52 unsigned char iv[128];
53
54 if (tfm == NULL) {
55 BT_ERR("tfm %p", tfm);
56 return -EINVAL;
57 }
58
59 desc.tfm = tfm;
60 desc.flags = 0;
61
62 err = crypto_blkcipher_setkey(tfm, k, 16);
63 if (err) {
64 BT_ERR("cipher setkey failed: %d", err);
65 return err;
66 }
67
68 sg_init_one(&sg, r, 16);
69
70 iv_len = crypto_blkcipher_ivsize(tfm);
71 if (iv_len) {
72 memset(&iv, 0xff, iv_len);
73 crypto_blkcipher_set_iv(tfm, iv, iv_len);
74 }
75
76 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
77 if (err)
78 BT_ERR("Encrypt data error %d", err);
79
80 return err;
81}
82
83static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
84 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
85 u8 _rat, bdaddr_t *ra, u8 res[16])
86{
87 u8 p1[16], p2[16];
88 int err;
89
90 memset(p1, 0, 16);
91
92 /* p1 = pres || preq || _rat || _iat */
93 swap56(pres, p1);
94 swap56(preq, p1 + 7);
95 p1[14] = _rat;
96 p1[15] = _iat;
97
98 memset(p2, 0, 16);
99
100 /* p2 = padding || ia || ra */
101 baswap((bdaddr_t *) (p2 + 4), ia);
102 baswap((bdaddr_t *) (p2 + 10), ra);
103
104 /* res = r XOR p1 */
105 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
106
107 /* res = e(k, res) */
108 err = smp_e(tfm, k, res);
109 if (err) {
110 BT_ERR("Encrypt data error");
111 return err;
112 }
113
114 /* res = res XOR p2 */
115 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
116
117 /* res = e(k, res) */
118 err = smp_e(tfm, k, res);
119 if (err)
120 BT_ERR("Encrypt data error");
121
122 return err;
123}
124
125static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
126 u8 r1[16], u8 r2[16], u8 _r[16])
127{
128 int err;
129
130 /* Just least significant octets from r1 and r2 are considered */
131 memcpy(_r, r1 + 8, 8);
132 memcpy(_r + 8, r2 + 8, 8);
133
134 err = smp_e(tfm, k, _r);
135 if (err)
136 BT_ERR("Encrypt data error");
137
138 return err;
139}
140
141static int smp_rand(u8 *buf)
142{
143 get_random_bytes(buf, 16);
144
145 return 0;
146}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300147
148static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
149 u16 dlen, void *data)
150{
151 struct sk_buff *skb;
152 struct l2cap_hdr *lh;
153 int len;
154
155 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
156
157 if (len > conn->mtu)
158 return NULL;
159
160 skb = bt_skb_alloc(len, GFP_ATOMIC);
161 if (!skb)
162 return NULL;
163
164 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
165 lh->len = cpu_to_le16(sizeof(code) + dlen);
166 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
167
168 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
169
170 memcpy(skb_put(skb, dlen), data, dlen);
171
172 return skb;
173}
174
175static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
176{
177 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
178
179 BT_DBG("code 0x%2.2x", code);
180
181 if (!skb)
182 return;
183
184 hci_send_acl(conn->hcon, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300185
186 mod_timer(&conn->security_timer, jiffies +
187 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300188}
189
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300190static __u8 seclevel_to_authreq(__u8 level)
191{
192 switch (level) {
193 case BT_SECURITY_HIGH:
194 /* Right now we don't support bonding */
195 return SMP_AUTH_MITM;
196
197 default:
198 return SMP_AUTH_NONE;
199 }
200}
201
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300202static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300203 struct smp_cmd_pairing *req,
204 struct smp_cmd_pairing *rsp,
205 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300206{
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300207 u8 dist_keys;
208
209 dist_keys = 0;
210 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
211 dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
212 authreq |= SMP_AUTH_BONDING;
213 }
214
215 if (rsp == NULL) {
216 req->io_capability = conn->hcon->io_capability;
217 req->oob_flag = SMP_OOB_NOT_PRESENT;
218 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
219 req->init_key_dist = dist_keys;
220 req->resp_key_dist = dist_keys;
221 req->auth_req = authreq;
222 return;
223 }
224
225 rsp->io_capability = conn->hcon->io_capability;
226 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
227 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
228 rsp->init_key_dist = req->init_key_dist & dist_keys;
229 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
230 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300231}
232
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300233static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
234{
235 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
236 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
237 return SMP_ENC_KEY_SIZE;
238
239 conn->smp_key_size = max_key_size;
240
241 return 0;
242}
243
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300244static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300245{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300246 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
247 u8 key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300248
249 BT_DBG("conn %p", conn);
250
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300251 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
252 hci_conn_hold(conn->hcon);
253
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300254 conn->preq[0] = SMP_CMD_PAIRING_REQ;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300255 memcpy(&conn->preq[1], req, sizeof(*req));
256 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300257
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300258 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300259 return SMP_OOB_NOT_AVAIL;
260
261 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300262 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300263
264 key_size = min(req->max_key_size, rsp.max_key_size);
265 if (check_enc_key_size(conn, key_size))
266 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300267
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300268 /* Just works */
269 memset(conn->tk, 0, sizeof(conn->tk));
270
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300271 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300272 memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300273
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300274 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300275
276 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300277}
278
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300279static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300280{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300281 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300282 struct smp_cmd_pairing_confirm cp;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300283 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
284 int ret;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300285 u8 res[16], key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300286
287 BT_DBG("conn %p", conn);
288
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300289 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300290
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300291 req = (void *) &conn->preq[1];
292
293 key_size = min(req->max_key_size, rsp->max_key_size);
294 if (check_enc_key_size(conn, key_size))
295 return SMP_ENC_KEY_SIZE;
296
297 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300298 return SMP_OOB_NOT_AVAIL;
299
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300300 /* Just works */
301 memset(conn->tk, 0, sizeof(conn->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300302
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300303 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300304 memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300305
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300306 ret = smp_rand(conn->prnd);
307 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300308 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300309
310 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
311 conn->src, conn->hcon->dst_type, conn->dst, res);
312 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300313 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300314
315 swap128(res, cp.confirm_val);
316
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300317 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300318
319 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300320}
321
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300322static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300323{
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300324 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
325
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300326 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
327
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300328 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
329 skb_pull(skb, sizeof(conn->pcnf));
330
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300331 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300332 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300333
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300334 swap128(conn->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300335 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300336 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300337 } else {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300338 struct smp_cmd_pairing_confirm cp;
339 int ret;
340 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300341
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300342 ret = smp_rand(conn->prnd);
343 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300344 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300345
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300346 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
347 conn->hcon->dst_type, conn->dst,
348 0, conn->src, res);
349 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300350 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300351
352 swap128(res, cp.confirm_val);
353
354 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300355 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300356
357 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300358}
359
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300360static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300361{
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300362 struct hci_conn *hcon = conn->hcon;
363 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300364 int ret;
Vinicius Costa Gomes9b3d6742011-06-09 18:50:48 -0300365 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300366
367 swap128(skb->data, random);
368 skb_pull(skb, sizeof(random));
369
370 if (conn->hcon->out)
371 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
372 conn->src, conn->hcon->dst_type, conn->dst,
373 res);
374 else
375 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
376 conn->hcon->dst_type, conn->dst, 0, conn->src,
377 res);
378 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300379 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300380
381 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
382
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300383 swap128(res, confirm);
384
385 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300386 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300387 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300388 }
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300389
390 if (conn->hcon->out) {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300391 u8 stk[16], rand[8];
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300392 __le16 ediv;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300393
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300394 memset(rand, 0, sizeof(rand));
395 ediv = 0;
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300396
397 smp_s1(tfm, conn->tk, random, conn->prnd, key);
398 swap128(key, stk);
399
400 memset(stk + conn->smp_key_size, 0,
401 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
402
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300403 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
404 return SMP_UNSPECIFIED;
405
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300406 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300407 hcon->enc_key_size = conn->smp_key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300408 } else {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300409 u8 stk[16], r[16], rand[8];
410 __le16 ediv;
411
412 memset(rand, 0, sizeof(rand));
413 ediv = 0;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300414
415 swap128(conn->prnd, r);
416 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
417
418 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300419 swap128(key, stk);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300420
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300421 memset(stk + conn->smp_key_size, 0,
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300422 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300423
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300424 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, conn->smp_key_size,
425 ediv, rand, stk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300426 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300427
428 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300429}
430
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300431static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300432{
433 struct smp_cmd_security_req *rp = (void *) skb->data;
434 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300435 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300436
437 BT_DBG("conn %p", conn);
438
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300439 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300440 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300441
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300442 hci_conn_hold(hcon);
443
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300444 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300445
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300446 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300447 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300448
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300449 conn->preq[0] = SMP_CMD_PAIRING_REQ;
450 memcpy(&conn->preq[1], &cp, sizeof(cp));
451
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300452 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300453
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300454 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300455}
456
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300457int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
458{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300459 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300460 __u8 authreq;
461
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300462 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
463
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300464 if (!lmp_host_le_capable(hcon->hdev))
465 return 1;
466
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300467 if (IS_ERR(hcon->hdev->tfm))
468 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300469
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300470 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300471 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300472
473 if (hcon->sec_level >= sec_level)
474 return 1;
475
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300476 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300477 struct link_key *key;
478
479 key = hci_find_link_key_type(hcon->hdev, conn->dst,
480 HCI_LK_SMP_LTK);
481 if (key) {
482 struct key_master_id *master = (void *) key->data;
483
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300484 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
485 &hcon->pend))
486 goto done;
487
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300488 hci_le_start_enc(hcon, master->ediv, master->rand,
489 key->val);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300490 hcon->enc_key_size = key->pin_len;
491
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300492 goto done;
493 }
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300494 }
495
496 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
497 return 0;
498
499 /* While SMP is going on */
500 hci_conn_hold(hcon);
501
502 authreq = seclevel_to_authreq(sec_level);
503
504 if (hcon->link_mode & HCI_LM_MASTER) {
505 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300506
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300507 build_pairing_cmd(conn, &cp, NULL, authreq);
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300508 conn->preq[0] = SMP_CMD_PAIRING_REQ;
509 memcpy(&conn->preq[1], &cp, sizeof(cp));
510
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300511 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
512 } else {
513 struct smp_cmd_security_req cp;
514 cp.auth_req = authreq;
515 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
516 }
517
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300518done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300519 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300520
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300521 return 0;
522}
523
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300524static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
525{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300526 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
527
528 skb_pull(skb, sizeof(*rp));
529
530 memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
531
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300532 return 0;
533}
534
535static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
536{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300537 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300538
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300539 skb_pull(skb, sizeof(*rp));
540
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300541 hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size,
542 rp->ediv, rp->rand, conn->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300543
544 smp_distribute_keys(conn, 1);
545
546 return 0;
547}
548
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300549int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
550{
551 __u8 code = skb->data[0];
552 __u8 reason;
553 int err = 0;
554
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300555 if (!lmp_host_le_capable(conn->hcon->hdev)) {
556 err = -ENOTSUPP;
557 reason = SMP_PAIRING_NOTSUPP;
558 goto done;
559 }
560
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300561 if (IS_ERR(conn->hcon->hdev->tfm)) {
562 err = PTR_ERR(conn->hcon->hdev->tfm);
563 reason = SMP_PAIRING_NOTSUPP;
564 goto done;
565 }
566
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300567 skb_pull(skb, sizeof(code));
568
569 switch (code) {
570 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300571 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300572 break;
573
574 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300575 reason = 0;
576 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300577 break;
578
579 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300580 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300581 break;
582
583 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300584 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300585 break;
586
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300587 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300588 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300589 break;
590
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300591 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300592 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300593 break;
594
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300595 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300596 reason = smp_cmd_encrypt_info(conn, skb);
597 break;
598
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300599 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300600 reason = smp_cmd_master_ident(conn, skb);
601 break;
602
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300603 case SMP_CMD_IDENT_INFO:
604 case SMP_CMD_IDENT_ADDR_INFO:
605 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300606 /* Just ignored */
607 reason = 0;
608 break;
609
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300610 default:
611 BT_DBG("Unknown command code 0x%2.2x", code);
612
613 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300614 err = -EOPNOTSUPP;
615 goto done;
616 }
617
618done:
619 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300620 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
621 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300622
623 kfree_skb(skb);
624 return err;
625}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300626
627int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
628{
629 struct smp_cmd_pairing *req, *rsp;
630 __u8 *keydist;
631
632 BT_DBG("conn %p force %d", conn, force);
633
634 if (IS_ERR(conn->hcon->hdev->tfm))
635 return PTR_ERR(conn->hcon->hdev->tfm);
636
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300637 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
638 return 0;
639
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300640 rsp = (void *) &conn->prsp[1];
641
642 /* The responder sends its keys first */
643 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
644 return 0;
645
646 req = (void *) &conn->preq[1];
647
648 if (conn->hcon->out) {
649 keydist = &rsp->init_key_dist;
650 *keydist &= req->init_key_dist;
651 } else {
652 keydist = &rsp->resp_key_dist;
653 *keydist &= req->resp_key_dist;
654 }
655
656
657 BT_DBG("keydist 0x%x", *keydist);
658
659 if (*keydist & SMP_DIST_ENC_KEY) {
660 struct smp_cmd_encrypt_info enc;
661 struct smp_cmd_master_ident ident;
662 __le16 ediv;
663
664 get_random_bytes(enc.ltk, sizeof(enc.ltk));
665 get_random_bytes(&ediv, sizeof(ediv));
666 get_random_bytes(ident.rand, sizeof(ident.rand));
667
668 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
669
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300670 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, conn->smp_key_size,
671 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300672
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300673 ident.ediv = cpu_to_le16(ediv);
674
675 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
676
677 *keydist &= ~SMP_DIST_ENC_KEY;
678 }
679
680 if (*keydist & SMP_DIST_ID_KEY) {
681 struct smp_cmd_ident_addr_info addrinfo;
682 struct smp_cmd_ident_info idinfo;
683
684 /* Send a dummy key */
685 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
686
687 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
688
689 /* Just public address */
690 memset(&addrinfo, 0, sizeof(addrinfo));
691 bacpy(&addrinfo.bdaddr, conn->src);
692
693 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
694 &addrinfo);
695
696 *keydist &= ~SMP_DIST_ID_KEY;
697 }
698
699 if (*keydist & SMP_DIST_SIGN) {
700 struct smp_cmd_sign_info sign;
701
702 /* Send a dummy key */
703 get_random_bytes(sign.csrk, sizeof(sign.csrk));
704
705 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
706
707 *keydist &= ~SMP_DIST_SIGN;
708 }
709
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300710 if (conn->hcon->out || force) {
711 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
712 del_timer(&conn->security_timer);
713 hci_conn_put(conn->hcon);
714 }
715
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300716 return 0;
717}