blob: a8b971b75a67a7f4c2a5675e5ebebb888cfe5245 [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);
185}
186
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300187static __u8 seclevel_to_authreq(__u8 level)
188{
189 switch (level) {
190 case BT_SECURITY_HIGH:
191 /* Right now we don't support bonding */
192 return SMP_AUTH_MITM;
193
194 default:
195 return SMP_AUTH_NONE;
196 }
197}
198
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300199static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300200 struct smp_cmd_pairing *req,
201 struct smp_cmd_pairing *rsp,
202 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300203{
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300204 u8 dist_keys;
205
206 dist_keys = 0;
207 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
208 dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
209 authreq |= SMP_AUTH_BONDING;
210 }
211
212 if (rsp == NULL) {
213 req->io_capability = conn->hcon->io_capability;
214 req->oob_flag = SMP_OOB_NOT_PRESENT;
215 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
216 req->init_key_dist = dist_keys;
217 req->resp_key_dist = dist_keys;
218 req->auth_req = authreq;
219 return;
220 }
221
222 rsp->io_capability = conn->hcon->io_capability;
223 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
224 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
225 rsp->init_key_dist = req->init_key_dist & dist_keys;
226 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
227 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300228}
229
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300230static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
231{
232 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
233 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
234 return SMP_ENC_KEY_SIZE;
235
236 conn->smp_key_size = max_key_size;
237
238 return 0;
239}
240
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300241static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300242{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300243 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
244 u8 key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300245
246 BT_DBG("conn %p", conn);
247
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300248 conn->preq[0] = SMP_CMD_PAIRING_REQ;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300249 memcpy(&conn->preq[1], req, sizeof(*req));
250 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300251
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300252 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300253 return SMP_OOB_NOT_AVAIL;
254
255 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300256 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300257
258 key_size = min(req->max_key_size, rsp.max_key_size);
259 if (check_enc_key_size(conn, key_size))
260 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300261
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300262 /* Just works */
263 memset(conn->tk, 0, sizeof(conn->tk));
264
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300265 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300266 memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300267
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300268 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300269
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300270 mod_timer(&conn->security_timer, jiffies +
271 msecs_to_jiffies(SMP_TIMEOUT));
272
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300273 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300274}
275
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300276static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300277{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300278 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300279 struct smp_cmd_pairing_confirm cp;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300280 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
281 int ret;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300282 u8 res[16], key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300283
284 BT_DBG("conn %p", conn);
285
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300286 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300287
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300288 req = (void *) &conn->preq[1];
289
290 key_size = min(req->max_key_size, rsp->max_key_size);
291 if (check_enc_key_size(conn, key_size))
292 return SMP_ENC_KEY_SIZE;
293
294 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300295 return SMP_OOB_NOT_AVAIL;
296
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300297 /* Just works */
298 memset(conn->tk, 0, sizeof(conn->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300299
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300300 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300301 memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300302
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300303 ret = smp_rand(conn->prnd);
304 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300305 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300306
307 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
308 conn->src, conn->hcon->dst_type, conn->dst, res);
309 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300310 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300311
312 swap128(res, cp.confirm_val);
313
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300314 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300315
316 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300317}
318
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300319static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300320{
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300321 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
322
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300323 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
324
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300325 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
326 skb_pull(skb, sizeof(conn->pcnf));
327
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300328 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300329 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300330
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300331 swap128(conn->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300332 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300333 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300334 } else {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300335 struct smp_cmd_pairing_confirm cp;
336 int ret;
337 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300338
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300339 ret = smp_rand(conn->prnd);
340 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300341 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300342
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300343 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
344 conn->hcon->dst_type, conn->dst,
345 0, conn->src, res);
346 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300347 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300348
349 swap128(res, cp.confirm_val);
350
351 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300352 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300353
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300354 mod_timer(&conn->security_timer, jiffies +
355 msecs_to_jiffies(SMP_TIMEOUT));
356
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300357 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
403 hci_le_start_enc(hcon, ediv, rand, stk);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300404 } else {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300405 u8 stk[16], r[16], rand[8];
406 __le16 ediv;
407
408 memset(rand, 0, sizeof(rand));
409 ediv = 0;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300410
411 swap128(conn->prnd, r);
412 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
413
414 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300415 swap128(key, stk);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300416
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300417 memset(stk + conn->smp_key_size, 0,
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300418 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300419
420 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, ediv, rand, stk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300421 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300422
423 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300424}
425
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300426static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300427{
428 struct smp_cmd_security_req *rp = (void *) skb->data;
429 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300430 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300431
432 BT_DBG("conn %p", conn);
433
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300434 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300435 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300436
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300437 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300438
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300439 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300440 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300441
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300442 conn->preq[0] = SMP_CMD_PAIRING_REQ;
443 memcpy(&conn->preq[1], &cp, sizeof(cp));
444
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300445 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300446
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300447 mod_timer(&conn->security_timer, jiffies +
448 msecs_to_jiffies(SMP_TIMEOUT));
449
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300450 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300451
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300452 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300453}
454
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300455int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
456{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300457 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300458 __u8 authreq;
459
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300460 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
461
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300462 if (!lmp_host_le_capable(hcon->hdev))
463 return 1;
464
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300465 if (IS_ERR(hcon->hdev->tfm))
466 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300467
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300468 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
469 return 0;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300470
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300471 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300472 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300473
474 if (hcon->sec_level >= sec_level)
475 return 1;
476
477 authreq = seclevel_to_authreq(sec_level);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300478
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300479 if (hcon->link_mode & HCI_LM_MASTER) {
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300480 struct smp_cmd_pairing cp;
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300481 struct link_key *key;
482
483 key = hci_find_link_key_type(hcon->hdev, conn->dst,
484 HCI_LK_SMP_LTK);
485 if (key) {
486 struct key_master_id *master = (void *) key->data;
487
488 hci_le_start_enc(hcon, master->ediv, master->rand,
489 key->val);
490 goto done;
491 }
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300492
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300493 build_pairing_cmd(conn, &cp, NULL, authreq);
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300494 conn->preq[0] = SMP_CMD_PAIRING_REQ;
495 memcpy(&conn->preq[1], &cp, sizeof(cp));
496
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300497 mod_timer(&conn->security_timer, jiffies +
498 msecs_to_jiffies(SMP_TIMEOUT));
499
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300500 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
501 } else {
502 struct smp_cmd_security_req cp;
503 cp.auth_req = authreq;
504 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
505 }
506
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300507done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300508 hcon->pending_sec_level = sec_level;
509 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
510
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300511 return 0;
512}
513
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300514static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
515{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300516 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
517
518 skb_pull(skb, sizeof(*rp));
519
520 memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
521
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300522 return 0;
523}
524
525static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
526{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300527 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300528
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300529 skb_pull(skb, sizeof(*rp));
530
531 hci_add_ltk(conn->hcon->hdev, 1, conn->src, rp->ediv,
532 rp->rand, conn->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300533
534 smp_distribute_keys(conn, 1);
535
536 return 0;
537}
538
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300539int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
540{
541 __u8 code = skb->data[0];
542 __u8 reason;
543 int err = 0;
544
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300545 if (!lmp_host_le_capable(conn->hcon->hdev)) {
546 err = -ENOTSUPP;
547 reason = SMP_PAIRING_NOTSUPP;
548 goto done;
549 }
550
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300551 if (IS_ERR(conn->hcon->hdev->tfm)) {
552 err = PTR_ERR(conn->hcon->hdev->tfm);
553 reason = SMP_PAIRING_NOTSUPP;
554 goto done;
555 }
556
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300557 skb_pull(skb, sizeof(code));
558
559 switch (code) {
560 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300561 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300562 break;
563
564 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300565 reason = 0;
566 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300567 break;
568
569 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300570 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571 break;
572
573 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300574 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300575 break;
576
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300577 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300578 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300579 break;
580
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300581 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300582 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300583 break;
584
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300585 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300586 reason = smp_cmd_encrypt_info(conn, skb);
587 break;
588
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300589 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300590 reason = smp_cmd_master_ident(conn, skb);
591 break;
592
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300593 case SMP_CMD_IDENT_INFO:
594 case SMP_CMD_IDENT_ADDR_INFO:
595 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300596 /* Just ignored */
597 reason = 0;
598 break;
599
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300600 default:
601 BT_DBG("Unknown command code 0x%2.2x", code);
602
603 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300604 err = -EOPNOTSUPP;
605 goto done;
606 }
607
608done:
609 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300610 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
611 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300612
613 kfree_skb(skb);
614 return err;
615}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300616
617int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
618{
619 struct smp_cmd_pairing *req, *rsp;
620 __u8 *keydist;
621
622 BT_DBG("conn %p force %d", conn, force);
623
624 if (IS_ERR(conn->hcon->hdev->tfm))
625 return PTR_ERR(conn->hcon->hdev->tfm);
626
627 rsp = (void *) &conn->prsp[1];
628
629 /* The responder sends its keys first */
630 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
631 return 0;
632
633 req = (void *) &conn->preq[1];
634
635 if (conn->hcon->out) {
636 keydist = &rsp->init_key_dist;
637 *keydist &= req->init_key_dist;
638 } else {
639 keydist = &rsp->resp_key_dist;
640 *keydist &= req->resp_key_dist;
641 }
642
643
644 BT_DBG("keydist 0x%x", *keydist);
645
646 if (*keydist & SMP_DIST_ENC_KEY) {
647 struct smp_cmd_encrypt_info enc;
648 struct smp_cmd_master_ident ident;
649 __le16 ediv;
650
651 get_random_bytes(enc.ltk, sizeof(enc.ltk));
652 get_random_bytes(&ediv, sizeof(ediv));
653 get_random_bytes(ident.rand, sizeof(ident.rand));
654
655 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
656
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300657 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, ediv,
658 ident.rand, enc.ltk);
659
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300660 ident.ediv = cpu_to_le16(ediv);
661
662 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
663
664 *keydist &= ~SMP_DIST_ENC_KEY;
665 }
666
667 if (*keydist & SMP_DIST_ID_KEY) {
668 struct smp_cmd_ident_addr_info addrinfo;
669 struct smp_cmd_ident_info idinfo;
670
671 /* Send a dummy key */
672 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
673
674 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
675
676 /* Just public address */
677 memset(&addrinfo, 0, sizeof(addrinfo));
678 bacpy(&addrinfo.bdaddr, conn->src);
679
680 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
681 &addrinfo);
682
683 *keydist &= ~SMP_DIST_ID_KEY;
684 }
685
686 if (*keydist & SMP_DIST_SIGN) {
687 struct smp_cmd_sign_info sign;
688
689 /* Send a dummy key */
690 get_random_bytes(sign.csrk, sizeof(sign.csrk));
691
692 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
693
694 *keydist &= ~SMP_DIST_SIGN;
695 }
696
697 return 0;
698}