blob: e1c4ef37f2a8e0aee66584703ed37d4506c8c8bc [file] [log] [blame]
Anderson Briglia133e14c2011-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 Briglia8e7a3c52011-06-09 18:50:44 -030027#include <linux/crypto.h>
28#include <crypto/b128ops.h>
29
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -030030#define SMP_TIMEOUT 30000 /* 30 seconds */
31
Anderson Briglia8e7a3c52011-06-09 18:50:44 -030032static inline void swap128(u8 src[16], u8 dst[16])
33{
34 int i;
35 for (i = 0; i < 16; i++)
36 dst[15 - i] = src[i];
37}
38
39static inline void swap56(u8 src[7], u8 dst[7])
40{
41 int i;
42 for (i = 0; i < 7; i++)
43 dst[6 - i] = src[i];
44}
45
46static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
47{
48 struct blkcipher_desc desc;
49 struct scatterlist sg;
50 int err, iv_len;
51 unsigned char iv[128];
52
53 if (tfm == NULL) {
54 BT_ERR("tfm %p", tfm);
55 return -EINVAL;
56 }
57
58 desc.tfm = tfm;
59 desc.flags = 0;
60
61 err = crypto_blkcipher_setkey(tfm, k, 16);
62 if (err) {
63 BT_ERR("cipher setkey failed: %d", err);
64 return err;
65 }
66
67 sg_init_one(&sg, r, 16);
68
69 iv_len = crypto_blkcipher_ivsize(tfm);
70 if (iv_len) {
71 memset(&iv, 0xff, iv_len);
72 crypto_blkcipher_set_iv(tfm, iv, iv_len);
73 }
74
75 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
76 if (err)
77 BT_ERR("Encrypt data error %d", err);
78
79 return err;
80}
81
82static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
83 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
84 u8 _rat, bdaddr_t *ra, u8 res[16])
85{
86 u8 p1[16], p2[16];
87 int err;
88
89 memset(p1, 0, 16);
90
91 /* p1 = pres || preq || _rat || _iat */
92 swap56(pres, p1);
93 swap56(preq, p1 + 7);
94 p1[14] = _rat;
95 p1[15] = _iat;
96
97 memset(p2, 0, 16);
98
99 /* p2 = padding || ia || ra */
100 baswap((bdaddr_t *) (p2 + 4), ia);
101 baswap((bdaddr_t *) (p2 + 10), ra);
102
103 /* res = r XOR p1 */
104 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
105
106 /* res = e(k, res) */
107 err = smp_e(tfm, k, res);
108 if (err) {
109 BT_ERR("Encrypt data error");
110 return err;
111 }
112
113 /* res = res XOR p2 */
114 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
115
116 /* res = e(k, res) */
117 err = smp_e(tfm, k, res);
118 if (err)
119 BT_ERR("Encrypt data error");
120
121 return err;
122}
123
124static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
125 u8 r1[16], u8 r2[16], u8 _r[16])
126{
127 int err;
128
129 /* Just least significant octets from r1 and r2 are considered */
130 memcpy(_r, r1 + 8, 8);
131 memcpy(_r + 8, r2 + 8, 8);
132
133 err = smp_e(tfm, k, _r);
134 if (err)
135 BT_ERR("Encrypt data error");
136
137 return err;
138}
139
140static int smp_rand(u8 *buf)
141{
142 get_random_bytes(buf, 16);
143
144 return 0;
145}
Anderson Briglia133e14c2011-06-09 18:50:40 -0300146
147static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 u16 dlen, void *data)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300149{
150 struct sk_buff *skb;
151 struct l2cap_hdr *lh;
152 int len;
153
154 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
155
156 if (len > conn->mtu)
157 return NULL;
158
159 skb = bt_skb_alloc(len, GFP_ATOMIC);
160 if (!skb)
161 return NULL;
162
163 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
164 lh->len = cpu_to_le16(sizeof(code) + dlen);
165 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
166
167 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
168
169 memcpy(skb_put(skb, dlen), data, dlen);
170
171 return skb;
172}
173
174static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
175{
176 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
177
178 BT_DBG("code 0x%2.2x", code);
179
180 if (!skb)
181 return;
182
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700183 hci_send_acl(conn->hcon, NULL, skb, 0);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300184}
185
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300186static __u8 seclevel_to_authreq(__u8 level)
187{
188 switch (level) {
189 case BT_SECURITY_HIGH:
190 /* Right now we don't support bonding */
191 return SMP_AUTH_MITM;
192
193 default:
194 return SMP_AUTH_NONE;
195 }
196}
197
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300198static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300199 struct smp_cmd_pairing *req,
200 struct smp_cmd_pairing *rsp,
201 __u8 authreq)
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300202{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700203 u8 all_keys = 0;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300204 u8 dist_keys;
205
206 dist_keys = 0;
207 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300209 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;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217 req->resp_key_dist = all_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300218 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;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300226 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
227 rsp->auth_req = authreq;
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300228}
229
Vinicius Costa Gomes397d9ae2011-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 Gomes64532ec2011-06-09 18:50:53 -0300241static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300242{
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300243 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
244 u8 key_size;
Anderson Briglia13b48392011-06-09 18:50:42 -0300245
246 BT_DBG("conn %p", conn);
247
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300248 conn->preq[0] = SMP_CMD_PAIRING_REQ;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300249 memcpy(&conn->preq[1], req, sizeof(*req));
250 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300251
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300252 if (req->oob_flag)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300253 return SMP_OOB_NOT_AVAIL;
254
255 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300256 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes397d9ae2011-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 Briglia13b48392011-06-09 18:50:42 -0300261
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300262 /* Just works */
263 memset(conn->tk, 0, sizeof(conn->tk));
264
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300265 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300266 memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300267
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300268 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300269
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300270 mod_timer(&conn->security_timer, jiffies +
271 msecs_to_jiffies(SMP_TIMEOUT));
272
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300273 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300274}
275
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300276static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300277{
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300278 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Anderson Briglia13b48392011-06-09 18:50:42 -0300279 struct smp_cmd_pairing_confirm cp;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300280 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
281 int ret;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300282 u8 res[16], key_size;
Anderson Briglia13b48392011-06-09 18:50:42 -0300283
284 BT_DBG("conn %p", conn);
285
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300286 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300287
Vinicius Costa Gomes397d9ae2011-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 Gomes64532ec2011-06-09 18:50:53 -0300295 return SMP_OOB_NOT_AVAIL;
296
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300297 /* Just works */
298 memset(conn->tk, 0, sizeof(conn->tk));
Anderson Briglia13b48392011-06-09 18:50:42 -0300299
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300300 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300301 memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300302
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300303 ret = smp_rand(conn->prnd);
304 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300305 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-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 Gomes64532ec2011-06-09 18:50:53 -0300310 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300311
312 swap128(res, cp.confirm_val);
313
Anderson Briglia13b48392011-06-09 18:50:42 -0300314 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300315
316 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300317}
318
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300319static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300320{
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300321 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
322
Anderson Briglia13b48392011-06-09 18:50:42 -0300323 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
324
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300325 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
326 skb_pull(skb, sizeof(conn->pcnf));
327
Anderson Briglia13b48392011-06-09 18:50:42 -0300328 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300329 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300330
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300331 swap128(conn->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300332 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300333 random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300334 } else {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300335 struct smp_cmd_pairing_confirm cp;
336 int ret;
337 u8 res[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300338
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300339 ret = smp_rand(conn->prnd);
340 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300341 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300342
Anderson Briglia21b8a2b2011-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 Gomes64532ec2011-06-09 18:50:53 -0300347 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-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 Briglia13b48392011-06-09 18:50:42 -0300352 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300353
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300354 mod_timer(&conn->security_timer, jiffies +
355 msecs_to_jiffies(SMP_TIMEOUT));
356
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300357 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300358}
359
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300360static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300361{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300362 struct hci_conn *hcon = conn->hcon;
363 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300364 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300365 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-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 Gomes64532ec2011-06-09 18:50:53 -0300379 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300380
381 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
382
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300383 swap128(res, confirm);
384
385 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300386 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300387 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300388 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300389
390 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300391 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300392 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300393
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300394 memset(rand, 0, sizeof(rand));
395 ediv = 0;
Vinicius Costa Gomesf1b45c52011-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);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300404 hcon->enc_key_size = conn->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300405 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300406 u8 stk[16], r[16], rand[8];
407 __le16 ediv;
408
409 memset(rand, 0, sizeof(rand));
410 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300411
412 swap128(conn->prnd, r);
413 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
414
415 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300416 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300417
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300418 memset(stk + conn->smp_key_size, 0,
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300419 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300420
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300421 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, conn->smp_key_size,
422 ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300423 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300424
425 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300426}
427
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300428static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300429{
430 struct smp_cmd_security_req *rp = (void *) skb->data;
431 struct smp_cmd_pairing cp;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300432 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300433
434 BT_DBG("conn %p", conn);
435
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300436 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300437 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300438
Anderson Briglia13b48392011-06-09 18:50:42 -0300439 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300440
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300441 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300442 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300443
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300444 conn->preq[0] = SMP_CMD_PAIRING_REQ;
445 memcpy(&conn->preq[1], &cp, sizeof(cp));
446
Anderson Briglia13b48392011-06-09 18:50:42 -0300447 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300448
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300449 mod_timer(&conn->security_timer, jiffies +
450 msecs_to_jiffies(SMP_TIMEOUT));
451
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300452 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300453
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300454 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300455}
456
Anderson Briglia133e14c2011-06-09 18:50:40 -0300457int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
458{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300459 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300460 __u8 authreq;
461
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300462 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
463
464 if (IS_ERR(hcon->hdev->tfm))
465 return 1;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300466
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300467 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300469
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300470 if (sec_level == BT_SECURITY_LOW)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300471 return 1;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300472
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700473 if (hcon->sec_level > sec_level)
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300474 return 1;
475
476 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300477
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300478 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300479 struct link_key *key;
480
481 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700482 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300483 if (key) {
484 struct key_master_id *master = (void *) key->data;
485
486 hci_le_start_enc(hcon, master->ediv, master->rand,
487 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300488 hcon->enc_key_size = key->pin_len;
489
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300490 goto done;
491 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 }
493
494 if (hcon->link_mode & HCI_LM_MASTER) {
495 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300496
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300497 build_pairing_cmd(conn, &cp, NULL, authreq);
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300498 conn->preq[0] = SMP_CMD_PAIRING_REQ;
499 memcpy(&conn->preq[1], &cp, sizeof(cp));
500
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300501 mod_timer(&conn->security_timer, jiffies +
502 msecs_to_jiffies(SMP_TIMEOUT));
503
Anderson Briglia133e14c2011-06-09 18:50:40 -0300504 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
505 } else {
506 struct smp_cmd_security_req cp;
507 cp.auth_req = authreq;
508 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
509 }
510
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300511done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300512 hcon->pending_sec_level = sec_level;
513 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
514
Anderson Briglia133e14c2011-06-09 18:50:40 -0300515 return 0;
516}
517
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300518static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
519{
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300520 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521 u8 rand[8];
522 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300523
524 skb_pull(skb, sizeof(*rp));
525
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 BT_DBG("conn %p", conn);
527
528 memset(rand, 0, sizeof(rand));
529
530 err = hci_add_ltk(conn->hcon->hdev, 0, conn->dst, 0, 0, rand, rp->ltk);
531 if (err)
532 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300533
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300534 return 0;
535}
536
537static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
538{
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300539 struct smp_cmd_master_ident *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540 struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
541 struct link_key *key;
542 struct key_master_id *id;
543 u8 keydist = paircmd->init_key_dist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300544
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300545 skb_pull(skb, sizeof(*rp));
546
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547 key = hci_find_link_key_type(conn->hcon->hdev, conn->dst, KEY_TYPE_LTK);
548 if (key == NULL)
549 return SMP_UNSPECIFIED;
550
551 BT_DBG("keydist 0x%x", keydist);
552
553 id = (void *) key->data;
554 id->ediv = rp->ediv;
555 memcpy(id->rand, rp->rand, sizeof(rp->rand));
556
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300557 hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558 rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300559
560 smp_distribute_keys(conn, 1);
561
562 return 0;
563}
564
Anderson Briglia133e14c2011-06-09 18:50:40 -0300565int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
566{
567 __u8 code = skb->data[0];
568 __u8 reason;
569 int err = 0;
570
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300571 if (IS_ERR(conn->hcon->hdev->tfm)) {
572 err = PTR_ERR(conn->hcon->hdev->tfm);
573 reason = SMP_PAIRING_NOTSUPP;
574 goto done;
575 }
576
Anderson Briglia133e14c2011-06-09 18:50:40 -0300577 skb_pull(skb, sizeof(code));
578
579 switch (code) {
580 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300581 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300582 break;
583
584 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300585 reason = 0;
586 err = -EPERM;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300587 break;
588
589 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300590 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300591 break;
592
593 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300594 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300595 break;
596
Anderson Briglia133e14c2011-06-09 18:50:40 -0300597 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300598 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300599 break;
600
Anderson Briglia133e14c2011-06-09 18:50:40 -0300601 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300602 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300603 break;
604
Anderson Briglia133e14c2011-06-09 18:50:40 -0300605 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300606 reason = smp_cmd_encrypt_info(conn, skb);
607 break;
608
Anderson Briglia133e14c2011-06-09 18:50:40 -0300609 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300610 reason = smp_cmd_master_ident(conn, skb);
611 break;
612
Anderson Briglia133e14c2011-06-09 18:50:40 -0300613 case SMP_CMD_IDENT_INFO:
614 case SMP_CMD_IDENT_ADDR_INFO:
615 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300616 /* Just ignored */
617 reason = 0;
618 break;
619
Anderson Briglia133e14c2011-06-09 18:50:40 -0300620 default:
621 BT_DBG("Unknown command code 0x%2.2x", code);
622
623 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300624 err = -EOPNOTSUPP;
625 goto done;
626 }
627
628done:
629 if (reason)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300630 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
631 &reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300632
633 kfree_skb(skb);
634 return err;
635}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300636
637int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
638{
639 struct smp_cmd_pairing *req, *rsp;
640 __u8 *keydist;
641
642 BT_DBG("conn %p force %d", conn, force);
643
644 if (IS_ERR(conn->hcon->hdev->tfm))
645 return PTR_ERR(conn->hcon->hdev->tfm);
646
647 rsp = (void *) &conn->prsp[1];
648
649 /* The responder sends its keys first */
650 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
651 return 0;
652
653 req = (void *) &conn->preq[1];
654
655 if (conn->hcon->out) {
656 keydist = &rsp->init_key_dist;
657 *keydist &= req->init_key_dist;
658 } else {
659 keydist = &rsp->resp_key_dist;
660 *keydist &= req->resp_key_dist;
661 }
662
663
664 BT_DBG("keydist 0x%x", *keydist);
665
666 if (*keydist & SMP_DIST_ENC_KEY) {
667 struct smp_cmd_encrypt_info enc;
668 struct smp_cmd_master_ident ident;
669 __le16 ediv;
670
671 get_random_bytes(enc.ltk, sizeof(enc.ltk));
672 get_random_bytes(&ediv, sizeof(ediv));
673 get_random_bytes(ident.rand, sizeof(ident.rand));
674
675 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
676
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300677 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, conn->smp_key_size,
678 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300679
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300680 ident.ediv = cpu_to_le16(ediv);
681
682 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
683
684 *keydist &= ~SMP_DIST_ENC_KEY;
685 }
686
687 if (*keydist & SMP_DIST_ID_KEY) {
688 struct smp_cmd_ident_addr_info addrinfo;
689 struct smp_cmd_ident_info idinfo;
690
691 /* Send a dummy key */
692 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
693
694 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
695
696 /* Just public address */
697 memset(&addrinfo, 0, sizeof(addrinfo));
698 bacpy(&addrinfo.bdaddr, conn->src);
699
700 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
701 &addrinfo);
702
703 *keydist &= ~SMP_DIST_ID_KEY;
704 }
705
706 if (*keydist & SMP_DIST_SIGN) {
707 struct smp_cmd_sign_info sign;
708
709 /* Send a dummy key */
710 get_random_bytes(sign.csrk, sizeof(sign.csrk));
711
712 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
713
714 *keydist &= ~SMP_DIST_SIGN;
715 }
716
717 return 0;
718}