blob: 20c82c7000acff34fcd8004cfc25ba0ec6c9de80 [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
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300251 conn->preq[0] = SMP_CMD_PAIRING_REQ;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300252 memcpy(&conn->preq[1], req, sizeof(*req));
253 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300254
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300255 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300256 return SMP_OOB_NOT_AVAIL;
257
258 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300259 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300260
261 key_size = min(req->max_key_size, rsp.max_key_size);
262 if (check_enc_key_size(conn, key_size))
263 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300264
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300265 /* Just works */
266 memset(conn->tk, 0, sizeof(conn->tk));
267
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300268 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300269 memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300270
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300271 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300272
273 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
354 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300355}
356
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300357static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300358{
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300359 struct hci_conn *hcon = conn->hcon;
360 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300361 int ret;
Vinicius Costa Gomes9b3d6742011-06-09 18:50:48 -0300362 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300363
364 swap128(skb->data, random);
365 skb_pull(skb, sizeof(random));
366
367 if (conn->hcon->out)
368 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
369 conn->src, conn->hcon->dst_type, conn->dst,
370 res);
371 else
372 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
373 conn->hcon->dst_type, conn->dst, 0, conn->src,
374 res);
375 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300376 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300377
378 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
379
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300380 swap128(res, confirm);
381
382 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300383 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300384 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300385 }
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300386
387 if (conn->hcon->out) {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300388 u8 stk[16], rand[8];
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300389 __le16 ediv;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300390
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300391 memset(rand, 0, sizeof(rand));
392 ediv = 0;
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300393
394 smp_s1(tfm, conn->tk, random, conn->prnd, key);
395 swap128(key, stk);
396
397 memset(stk + conn->smp_key_size, 0,
398 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
399
400 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300401 hcon->enc_key_size = conn->smp_key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300402 } else {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300403 u8 stk[16], r[16], rand[8];
404 __le16 ediv;
405
406 memset(rand, 0, sizeof(rand));
407 ediv = 0;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300408
409 swap128(conn->prnd, r);
410 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
411
412 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300413 swap128(key, stk);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300414
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300415 memset(stk + conn->smp_key_size, 0,
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300416 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300417
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300418 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, conn->smp_key_size,
419 ediv, rand, stk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300420 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300421
422 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300423}
424
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300425static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300426{
427 struct smp_cmd_security_req *rp = (void *) skb->data;
428 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300429 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300430
431 BT_DBG("conn %p", conn);
432
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300433 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300434 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300435
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300436 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300437
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300438 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300439 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300440
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300441 conn->preq[0] = SMP_CMD_PAIRING_REQ;
442 memcpy(&conn->preq[1], &cp, sizeof(cp));
443
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300444 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300445
446 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300447
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300448 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300449}
450
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300451int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
452{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300453 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300454 __u8 authreq;
455
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300456 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
457
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300458 if (!lmp_host_le_capable(hcon->hdev))
459 return 1;
460
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300461 if (IS_ERR(hcon->hdev->tfm))
462 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300463
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300464 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
465 return 0;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300466
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300467 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300468 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300469
470 if (hcon->sec_level >= sec_level)
471 return 1;
472
473 authreq = seclevel_to_authreq(sec_level);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300474
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300475 if (hcon->link_mode & HCI_LM_MASTER) {
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300476 struct smp_cmd_pairing cp;
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
484 hci_le_start_enc(hcon, master->ediv, master->rand,
485 key->val);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300486 hcon->enc_key_size = key->pin_len;
487
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300488 goto done;
489 }
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300490
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300491 build_pairing_cmd(conn, &cp, NULL, authreq);
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300492 conn->preq[0] = SMP_CMD_PAIRING_REQ;
493 memcpy(&conn->preq[1], &cp, sizeof(cp));
494
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300495 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
496 } else {
497 struct smp_cmd_security_req cp;
498 cp.auth_req = authreq;
499 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
500 }
501
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300502done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300503 hcon->pending_sec_level = sec_level;
504 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
505
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300506 return 0;
507}
508
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300509static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
510{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300511 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
512
513 skb_pull(skb, sizeof(*rp));
514
515 memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
516
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300517 return 0;
518}
519
520static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
521{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300522 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300523
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300524 skb_pull(skb, sizeof(*rp));
525
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300526 hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size,
527 rp->ediv, rp->rand, conn->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300528
529 smp_distribute_keys(conn, 1);
530
531 return 0;
532}
533
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300534int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
535{
536 __u8 code = skb->data[0];
537 __u8 reason;
538 int err = 0;
539
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300540 if (!lmp_host_le_capable(conn->hcon->hdev)) {
541 err = -ENOTSUPP;
542 reason = SMP_PAIRING_NOTSUPP;
543 goto done;
544 }
545
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300546 if (IS_ERR(conn->hcon->hdev->tfm)) {
547 err = PTR_ERR(conn->hcon->hdev->tfm);
548 reason = SMP_PAIRING_NOTSUPP;
549 goto done;
550 }
551
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300552 skb_pull(skb, sizeof(code));
553
554 switch (code) {
555 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300556 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300557 break;
558
559 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300560 reason = 0;
561 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300562 break;
563
564 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300565 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300566 break;
567
568 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300569 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300570 break;
571
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300572 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300573 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300574 break;
575
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300576 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300577 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300578 break;
579
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300580 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300581 reason = smp_cmd_encrypt_info(conn, skb);
582 break;
583
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300584 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300585 reason = smp_cmd_master_ident(conn, skb);
586 break;
587
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300588 case SMP_CMD_IDENT_INFO:
589 case SMP_CMD_IDENT_ADDR_INFO:
590 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300591 /* Just ignored */
592 reason = 0;
593 break;
594
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300595 default:
596 BT_DBG("Unknown command code 0x%2.2x", code);
597
598 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300599 err = -EOPNOTSUPP;
600 goto done;
601 }
602
603done:
604 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300605 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
606 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300607
608 kfree_skb(skb);
609 return err;
610}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300611
612int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
613{
614 struct smp_cmd_pairing *req, *rsp;
615 __u8 *keydist;
616
617 BT_DBG("conn %p force %d", conn, force);
618
619 if (IS_ERR(conn->hcon->hdev->tfm))
620 return PTR_ERR(conn->hcon->hdev->tfm);
621
622 rsp = (void *) &conn->prsp[1];
623
624 /* The responder sends its keys first */
625 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
626 return 0;
627
628 req = (void *) &conn->preq[1];
629
630 if (conn->hcon->out) {
631 keydist = &rsp->init_key_dist;
632 *keydist &= req->init_key_dist;
633 } else {
634 keydist = &rsp->resp_key_dist;
635 *keydist &= req->resp_key_dist;
636 }
637
638
639 BT_DBG("keydist 0x%x", *keydist);
640
641 if (*keydist & SMP_DIST_ENC_KEY) {
642 struct smp_cmd_encrypt_info enc;
643 struct smp_cmd_master_ident ident;
644 __le16 ediv;
645
646 get_random_bytes(enc.ltk, sizeof(enc.ltk));
647 get_random_bytes(&ediv, sizeof(ediv));
648 get_random_bytes(ident.rand, sizeof(ident.rand));
649
650 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
651
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300652 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, conn->smp_key_size,
653 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300654
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300655 ident.ediv = cpu_to_le16(ediv);
656
657 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
658
659 *keydist &= ~SMP_DIST_ENC_KEY;
660 }
661
662 if (*keydist & SMP_DIST_ID_KEY) {
663 struct smp_cmd_ident_addr_info addrinfo;
664 struct smp_cmd_ident_info idinfo;
665
666 /* Send a dummy key */
667 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
668
669 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
670
671 /* Just public address */
672 memset(&addrinfo, 0, sizeof(addrinfo));
673 bacpy(&addrinfo.bdaddr, conn->src);
674
675 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
676 &addrinfo);
677
678 *keydist &= ~SMP_DIST_ID_KEY;
679 }
680
681 if (*keydist & SMP_DIST_SIGN) {
682 struct smp_cmd_sign_info sign;
683
684 /* Send a dummy key */
685 get_random_bytes(sign.csrk, sizeof(sign.csrk));
686
687 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
688
689 *keydist &= ~SMP_DIST_SIGN;
690 }
691
692 return 0;
693}