blob: b5e1b4a300cc7313ef04f7ea3e98ea333fdad410 [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{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300235 struct smp_chan *smp = conn->smp_chan;
236
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300237 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
238 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
239 return SMP_ENC_KEY_SIZE;
240
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300241 smp->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300242
243 return 0;
244}
245
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300246static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300247{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300248 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300249 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300250 u8 key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300251
252 BT_DBG("conn %p", conn);
253
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300254 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
255 hci_conn_hold(conn->hcon);
256
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300257 smp->preq[0] = SMP_CMD_PAIRING_REQ;
258 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300259 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300260
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300261 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300262 return SMP_OOB_NOT_AVAIL;
263
264 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300265 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300266
267 key_size = min(req->max_key_size, rsp.max_key_size);
268 if (check_enc_key_size(conn, key_size))
269 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300270
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300271 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300272 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300273
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300274 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
275 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300276
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300277 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300278
279 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300280}
281
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300282static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300283{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300284 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300285 struct smp_cmd_pairing_confirm cp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300286 struct smp_chan *smp = conn->smp_chan;
287 struct crypto_blkcipher *tfm = smp->tfm;
288
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300289 int ret;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300290 u8 res[16], key_size;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300291
292 BT_DBG("conn %p", conn);
293
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300294 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300295
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300296 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300297
298 key_size = min(req->max_key_size, rsp->max_key_size);
299 if (check_enc_key_size(conn, key_size))
300 return SMP_ENC_KEY_SIZE;
301
302 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300303 return SMP_OOB_NOT_AVAIL;
304
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300305 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300306 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300307
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300308 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
309 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300310
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300311 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300312 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300313 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300314
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300315 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300316 conn->src, conn->hcon->dst_type, conn->dst, res);
317 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300318 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300319
320 swap128(res, cp.confirm_val);
321
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300322 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300323
324 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300325}
326
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300327static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300328{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300329 struct smp_chan *smp = conn->smp_chan;
330 struct crypto_blkcipher *tfm = smp->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300331
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300332 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
333
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300334 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
335 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300336
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300337 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300338 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300339
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300340 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300341 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300342 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300343 } else {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300344 struct smp_cmd_pairing_confirm cp;
345 int ret;
346 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300347
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300348 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300349 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300350 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300351
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300352 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300353 conn->hcon->dst_type, conn->dst,
354 0, conn->src, res);
355 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300356 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300357
358 swap128(res, cp.confirm_val);
359
360 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300361 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300362
363 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300364}
365
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300366static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300367{
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300368 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300369 struct smp_chan *smp = conn->smp_chan;
370 struct crypto_blkcipher *tfm = smp->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300371 int ret;
Vinicius Costa Gomes9b3d6742011-06-09 18:50:48 -0300372 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300373
374 swap128(skb->data, random);
375 skb_pull(skb, sizeof(random));
376
377 if (conn->hcon->out)
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300378 ret = smp_c1(tfm, smp->tk, random, smp->preq, smp->prsp, 0,
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300379 conn->src, conn->hcon->dst_type, conn->dst,
380 res);
381 else
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300382 ret = smp_c1(tfm, smp->tk, random, smp->preq, smp->prsp,
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300383 conn->hcon->dst_type, conn->dst, 0, conn->src,
384 res);
385 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300386 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300387
388 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
389
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300390 swap128(res, confirm);
391
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300392 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300393 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300394 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300395 }
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300396
397 if (conn->hcon->out) {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300398 u8 stk[16], rand[8];
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300399 __le16 ediv;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300400
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300401 memset(rand, 0, sizeof(rand));
402 ediv = 0;
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300403
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300404 smp_s1(tfm, smp->tk, random, smp->prnd, key);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300405 swap128(key, stk);
406
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300407 memset(stk + smp->smp_key_size, 0,
408 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300409
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300410 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
411 return SMP_UNSPECIFIED;
412
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300413 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300414 hcon->enc_key_size = smp->smp_key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300415 } else {
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300416 u8 stk[16], r[16], rand[8];
417 __le16 ediv;
418
419 memset(rand, 0, sizeof(rand));
420 ediv = 0;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300421
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300422 swap128(smp->prnd, r);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300423 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
424
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300425 smp_s1(tfm, smp->tk, smp->prnd, random, key);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300426 swap128(key, stk);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300427
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300428 memset(stk + smp->smp_key_size, 0,
429 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
Vinicius Costa Gomese7e62c82011-07-07 18:59:40 -0300430
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300431 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300432 ediv, rand, stk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300433 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300434
435 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300436}
437
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300438static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300439{
440 struct smp_cmd_security_req *rp = (void *) skb->data;
441 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300442 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300443 struct smp_chan *smp = conn->smp_chan;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300444
445 BT_DBG("conn %p", conn);
446
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300447 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300448 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300449
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300450 hci_conn_hold(hcon);
451
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300452 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300453
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300454 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300455 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300456
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300457 smp->preq[0] = SMP_CMD_PAIRING_REQ;
458 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300459
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300460 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300461
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300462 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300463}
464
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300465int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
466{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300467 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300468 struct smp_chan *smp = conn->smp_chan;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300469 __u8 authreq;
470
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300471 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
472
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300473 if (!lmp_host_le_capable(hcon->hdev))
474 return 1;
475
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300476 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300477 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300478
479 if (hcon->sec_level >= sec_level)
480 return 1;
481
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300482 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300483 struct link_key *key;
484
485 key = hci_find_link_key_type(hcon->hdev, conn->dst,
486 HCI_LK_SMP_LTK);
487 if (key) {
488 struct key_master_id *master = (void *) key->data;
489
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300490 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
491 &hcon->pend))
492 goto done;
493
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300494 hci_le_start_enc(hcon, master->ediv, master->rand,
495 key->val);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300496 hcon->enc_key_size = key->pin_len;
497
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300498 goto done;
499 }
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300500 }
501
502 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
503 return 0;
504
505 /* While SMP is going on */
506 hci_conn_hold(hcon);
507
508 authreq = seclevel_to_authreq(sec_level);
509
510 if (hcon->link_mode & HCI_LM_MASTER) {
511 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300512
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300513 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300514 smp->preq[0] = SMP_CMD_PAIRING_REQ;
515 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300516
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300517 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
518 } else {
519 struct smp_cmd_security_req cp;
520 cp.auth_req = authreq;
521 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
522 }
523
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300524done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300525 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300526
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300527 return 0;
528}
529
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300530static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
531{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300532 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300533 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300534
535 skb_pull(skb, sizeof(*rp));
536
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300537 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300538
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300539 return 0;
540}
541
542static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
543{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300544 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300545 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300546
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300547 skb_pull(skb, sizeof(*rp));
548
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300549 hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
550 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300551
552 smp_distribute_keys(conn, 1);
553
554 return 0;
555}
556
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300557int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
558{
559 __u8 code = skb->data[0];
560 __u8 reason;
561 int err = 0;
562
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300563 if (!lmp_host_le_capable(conn->hcon->hdev)) {
564 err = -ENOTSUPP;
565 reason = SMP_PAIRING_NOTSUPP;
566 goto done;
567 }
568
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300569 skb_pull(skb, sizeof(code));
570
571 switch (code) {
572 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300573 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300574 break;
575
576 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300577 reason = 0;
578 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300579 break;
580
581 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300582 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300583 break;
584
585 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300586 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300587 break;
588
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300589 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300590 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300591 break;
592
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300593 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300594 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300595 break;
596
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300597 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300598 reason = smp_cmd_encrypt_info(conn, skb);
599 break;
600
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300601 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300602 reason = smp_cmd_master_ident(conn, skb);
603 break;
604
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300605 case SMP_CMD_IDENT_INFO:
606 case SMP_CMD_IDENT_ADDR_INFO:
607 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300608 /* Just ignored */
609 reason = 0;
610 break;
611
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300612 default:
613 BT_DBG("Unknown command code 0x%2.2x", code);
614
615 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300616 err = -EOPNOTSUPP;
617 goto done;
618 }
619
620done:
621 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300622 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
623 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300624
625 kfree_skb(skb);
626 return err;
627}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300628
629int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
630{
631 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300632 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300633 __u8 *keydist;
634
635 BT_DBG("conn %p force %d", conn, force);
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 Gomes1c1def02011-09-05 14:31:30 -0300640 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300641
642 /* The responder sends its keys first */
643 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
644 return 0;
645
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300646 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300647
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 Gomes1c1def02011-09-05 14:31:30 -0300670 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300671 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}