blob: 39886786eb7ffd5c9d8918105702fe82fc1a0c76 [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>
28#include <crypto/b128ops.h>
29
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030030#define SMP_TIMEOUT 30000 /* 30 seconds */
31
Anderson Brigliad22ef0b2011-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 Brigliaeb492e02011-06-09 18:50:40 -0300146
147static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
148 u16 dlen, void *data)
149{
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
183 hci_send_acl(conn->hcon, skb, 0);
184}
185
Vinicius Costa Gomesda85e5e2011-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 Gomesb8e66ea2011-06-09 18:50:52 -0300198static void build_pairing_cmd(struct l2cap_conn *conn,
199 struct smp_cmd_pairing *cmd, __u8 authreq)
200{
201 cmd->io_capability = conn->hcon->io_capability;
202 cmd->oob_flag = SMP_OOB_NOT_PRESENT;
203 cmd->max_key_size = 16;
204 cmd->init_key_dist = 0x00;
205 cmd->resp_key_dist = 0x00;
206 cmd->auth_req = authreq;
207}
208
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300209static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300210{
211 struct smp_cmd_pairing *rp = (void *) skb->data;
212
213 BT_DBG("conn %p", conn);
214
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300215 conn->preq[0] = SMP_CMD_PAIRING_REQ;
216 memcpy(&conn->preq[1], rp, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300217 skb_pull(skb, sizeof(*rp));
218
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300219 if (rp->oob_flag)
220 return SMP_OOB_NOT_AVAIL;
221
222 /* We didn't start the pairing, so no requirements */
223 build_pairing_cmd(conn, rp, SMP_AUTH_NONE);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300224
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300225 /* Just works */
226 memset(conn->tk, 0, sizeof(conn->tk));
227
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300228 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
229 memcpy(&conn->prsp[1], rp, sizeof(*rp));
230
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300231 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300232
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300233 mod_timer(&conn->security_timer, jiffies +
234 msecs_to_jiffies(SMP_TIMEOUT));
235
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300236 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300237}
238
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300239static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300240{
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300241 struct smp_cmd_pairing *rp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300242 struct smp_cmd_pairing_confirm cp;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300243 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
244 int ret;
245 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300246
247 BT_DBG("conn %p", conn);
248
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300249 skb_pull(skb, sizeof(*rp));
250
251 if (rp->oob_flag)
252 return SMP_OOB_NOT_AVAIL;
253
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300254 /* Just works */
255 memset(conn->tk, 0, sizeof(conn->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300256
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300257 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
258 memcpy(&conn->prsp[1], rp, sizeof(*rp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300259
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300260 ret = smp_rand(conn->prnd);
261 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300262 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300263
264 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
265 conn->src, conn->hcon->dst_type, conn->dst, res);
266 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300267 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300268
269 swap128(res, cp.confirm_val);
270
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300271 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
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_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300277{
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300278 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
279
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300280 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
281
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300282 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
283 skb_pull(skb, sizeof(conn->pcnf));
284
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300285 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300286 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300287
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300288 swap128(conn->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300289 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300290 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300291 } else {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300292 struct smp_cmd_pairing_confirm cp;
293 int ret;
294 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300295
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300296 ret = smp_rand(conn->prnd);
297 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300298 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300299
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300300 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
301 conn->hcon->dst_type, conn->dst,
302 0, conn->src, res);
303 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300304 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300305
306 swap128(res, cp.confirm_val);
307
308 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300309 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300310
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300311 mod_timer(&conn->security_timer, jiffies +
312 msecs_to_jiffies(SMP_TIMEOUT));
313
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300314 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300315}
316
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300317static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300318{
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300319 struct hci_conn *hcon = conn->hcon;
320 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300321 int ret;
Vinicius Costa Gomes9b3d6742011-06-09 18:50:48 -0300322 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300323
324 swap128(skb->data, random);
325 skb_pull(skb, sizeof(random));
326
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300327 memset(hcon->ltk, 0, sizeof(hcon->ltk));
328
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300329 if (conn->hcon->out)
330 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
331 conn->src, conn->hcon->dst_type, conn->dst,
332 res);
333 else
334 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
335 conn->hcon->dst_type, conn->dst, 0, conn->src,
336 res);
337 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300338 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300339
340 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
341
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300342 swap128(res, confirm);
343
344 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300345 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300346 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300347 }
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300348
349 if (conn->hcon->out) {
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300350 __le16 ediv;
351 u8 rand[8];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300352
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300353 smp_s1(tfm, conn->tk, random, conn->prnd, key);
354 swap128(key, hcon->ltk);
355
356 memset(rand, 0, sizeof(rand));
357 ediv = 0;
358 hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300359 } else {
360 u8 r[16];
361
362 swap128(conn->prnd, r);
363 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
364
365 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300366 swap128(key, hcon->ltk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300367 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300368
369 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300370}
371
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300372static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300373{
374 struct smp_cmd_security_req *rp = (void *) skb->data;
375 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300376 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300377
378 BT_DBG("conn %p", conn);
379
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300380 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300381 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300382
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300383 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300384
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300385 memset(&cp, 0, sizeof(cp));
386 build_pairing_cmd(conn, &cp, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300387
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300388 conn->preq[0] = SMP_CMD_PAIRING_REQ;
389 memcpy(&conn->preq[1], &cp, sizeof(cp));
390
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300391 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300392
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300393 mod_timer(&conn->security_timer, jiffies +
394 msecs_to_jiffies(SMP_TIMEOUT));
395
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300396 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300397
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300398 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300399}
400
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300401int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
402{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300403 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300404 __u8 authreq;
405
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300406 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
407
408 if (IS_ERR(hcon->hdev->tfm))
409 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300410
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300411 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
412 return 0;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300413
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300414 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300415 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300416
417 if (hcon->sec_level >= sec_level)
418 return 1;
419
420 authreq = seclevel_to_authreq(sec_level);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300421
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300422 if (hcon->link_mode & HCI_LM_MASTER) {
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300423 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300424
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300425 build_pairing_cmd(conn, &cp, authreq);
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300426 conn->preq[0] = SMP_CMD_PAIRING_REQ;
427 memcpy(&conn->preq[1], &cp, sizeof(cp));
428
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300429 mod_timer(&conn->security_timer, jiffies +
430 msecs_to_jiffies(SMP_TIMEOUT));
431
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300432 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
433 } else {
434 struct smp_cmd_security_req cp;
435 cp.auth_req = authreq;
436 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
437 }
438
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300439 hcon->pending_sec_level = sec_level;
440 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
441
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300442 return 0;
443}
444
445int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
446{
447 __u8 code = skb->data[0];
448 __u8 reason;
449 int err = 0;
450
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300451 if (IS_ERR(conn->hcon->hdev->tfm)) {
452 err = PTR_ERR(conn->hcon->hdev->tfm);
453 reason = SMP_PAIRING_NOTSUPP;
454 goto done;
455 }
456
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300457 skb_pull(skb, sizeof(code));
458
459 switch (code) {
460 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300461 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300462 break;
463
464 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300465 reason = 0;
466 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300467 break;
468
469 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300470 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300471 break;
472
473 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300474 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300475 break;
476
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300477 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300478 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300479 break;
480
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300481 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300482 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300483 break;
484
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300485 case SMP_CMD_ENCRYPT_INFO:
486 case SMP_CMD_MASTER_IDENT:
487 case SMP_CMD_IDENT_INFO:
488 case SMP_CMD_IDENT_ADDR_INFO:
489 case SMP_CMD_SIGN_INFO:
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300490 default:
491 BT_DBG("Unknown command code 0x%2.2x", code);
492
493 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300494 err = -EOPNOTSUPP;
495 goto done;
496 }
497
498done:
499 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300500 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
501 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300502
503 kfree_skb(skb);
504 return err;
505}