blob: dfd6891b9c8640cce6be75b1ca83bb9f1c4113c9 [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
30static inline void swap128(u8 src[16], u8 dst[16])
31{
32 int i;
33 for (i = 0; i < 16; i++)
34 dst[15 - i] = src[i];
35}
36
37static inline void swap56(u8 src[7], u8 dst[7])
38{
39 int i;
40 for (i = 0; i < 7; i++)
41 dst[6 - i] = src[i];
42}
43
44static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
45{
46 struct blkcipher_desc desc;
47 struct scatterlist sg;
48 int err, iv_len;
49 unsigned char iv[128];
50
51 if (tfm == NULL) {
52 BT_ERR("tfm %p", tfm);
53 return -EINVAL;
54 }
55
56 desc.tfm = tfm;
57 desc.flags = 0;
58
59 err = crypto_blkcipher_setkey(tfm, k, 16);
60 if (err) {
61 BT_ERR("cipher setkey failed: %d", err);
62 return err;
63 }
64
65 sg_init_one(&sg, r, 16);
66
67 iv_len = crypto_blkcipher_ivsize(tfm);
68 if (iv_len) {
69 memset(&iv, 0xff, iv_len);
70 crypto_blkcipher_set_iv(tfm, iv, iv_len);
71 }
72
73 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
74 if (err)
75 BT_ERR("Encrypt data error %d", err);
76
77 return err;
78}
79
80static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
81 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
82 u8 _rat, bdaddr_t *ra, u8 res[16])
83{
84 u8 p1[16], p2[16];
85 int err;
86
87 memset(p1, 0, 16);
88
89 /* p1 = pres || preq || _rat || _iat */
90 swap56(pres, p1);
91 swap56(preq, p1 + 7);
92 p1[14] = _rat;
93 p1[15] = _iat;
94
95 memset(p2, 0, 16);
96
97 /* p2 = padding || ia || ra */
98 baswap((bdaddr_t *) (p2 + 4), ia);
99 baswap((bdaddr_t *) (p2 + 10), ra);
100
101 /* res = r XOR p1 */
102 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
103
104 /* res = e(k, res) */
105 err = smp_e(tfm, k, res);
106 if (err) {
107 BT_ERR("Encrypt data error");
108 return err;
109 }
110
111 /* res = res XOR p2 */
112 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
113
114 /* res = e(k, res) */
115 err = smp_e(tfm, k, res);
116 if (err)
117 BT_ERR("Encrypt data error");
118
119 return err;
120}
121
122static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
123 u8 r1[16], u8 r2[16], u8 _r[16])
124{
125 int err;
126
127 /* Just least significant octets from r1 and r2 are considered */
128 memcpy(_r, r1 + 8, 8);
129 memcpy(_r + 8, r2 + 8, 8);
130
131 err = smp_e(tfm, k, _r);
132 if (err)
133 BT_ERR("Encrypt data error");
134
135 return err;
136}
137
138static int smp_rand(u8 *buf)
139{
140 get_random_bytes(buf, 16);
141
142 return 0;
143}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300144
145static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
146 u16 dlen, void *data)
147{
148 struct sk_buff *skb;
149 struct l2cap_hdr *lh;
150 int len;
151
152 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
153
154 if (len > conn->mtu)
155 return NULL;
156
157 skb = bt_skb_alloc(len, GFP_ATOMIC);
158 if (!skb)
159 return NULL;
160
161 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
162 lh->len = cpu_to_le16(sizeof(code) + dlen);
163 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
164
165 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
166
167 memcpy(skb_put(skb, dlen), data, dlen);
168
169 return skb;
170}
171
172static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
173{
174 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
175
176 BT_DBG("code 0x%2.2x", code);
177
178 if (!skb)
179 return;
180
181 hci_send_acl(conn->hcon, skb, 0);
182}
183
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300184static __u8 seclevel_to_authreq(__u8 level)
185{
186 switch (level) {
187 case BT_SECURITY_HIGH:
188 /* Right now we don't support bonding */
189 return SMP_AUTH_MITM;
190
191 default:
192 return SMP_AUTH_NONE;
193 }
194}
195
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300196static void build_pairing_cmd(struct l2cap_conn *conn,
197 struct smp_cmd_pairing *cmd, __u8 authreq)
198{
199 cmd->io_capability = conn->hcon->io_capability;
200 cmd->oob_flag = SMP_OOB_NOT_PRESENT;
201 cmd->max_key_size = 16;
202 cmd->init_key_dist = 0x00;
203 cmd->resp_key_dist = 0x00;
204 cmd->auth_req = authreq;
205}
206
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300207static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300208{
209 struct smp_cmd_pairing *rp = (void *) skb->data;
210
211 BT_DBG("conn %p", conn);
212
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300213 conn->preq[0] = SMP_CMD_PAIRING_REQ;
214 memcpy(&conn->preq[1], rp, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300215 skb_pull(skb, sizeof(*rp));
216
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300217 if (rp->oob_flag)
218 return SMP_OOB_NOT_AVAIL;
219
220 /* We didn't start the pairing, so no requirements */
221 build_pairing_cmd(conn, rp, SMP_AUTH_NONE);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300222
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300223 /* Just works */
224 memset(conn->tk, 0, sizeof(conn->tk));
225
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300226 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
227 memcpy(&conn->prsp[1], rp, sizeof(*rp));
228
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300229 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300230
231 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300232}
233
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300234static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300235{
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300236 struct smp_cmd_pairing *rp = (void *) skb->data;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300237 struct smp_cmd_pairing_confirm cp;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300238 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
239 int ret;
240 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300241
242 BT_DBG("conn %p", conn);
243
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300244 skb_pull(skb, sizeof(*rp));
245
246 if (rp->oob_flag)
247 return SMP_OOB_NOT_AVAIL;
248
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300249 /* Just works */
250 memset(conn->tk, 0, sizeof(conn->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300251
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300252 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
253 memcpy(&conn->prsp[1], rp, sizeof(*rp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300254
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300255 ret = smp_rand(conn->prnd);
256 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300257 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300258
259 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
260 conn->src, conn->hcon->dst_type, conn->dst, res);
261 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300262 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300263
264 swap128(res, cp.confirm_val);
265
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300266 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300267
268 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300269}
270
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300271static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300272{
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300273 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
274
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300275 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
276
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300277 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
278 skb_pull(skb, sizeof(conn->pcnf));
279
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300280 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300281 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300282
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300283 swap128(conn->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300284 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300285 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300286 } else {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300287 struct smp_cmd_pairing_confirm cp;
288 int ret;
289 u8 res[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300290
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300291 ret = smp_rand(conn->prnd);
292 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300293 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300294
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300295 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
296 conn->hcon->dst_type, conn->dst,
297 0, conn->src, res);
298 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300299 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300300
301 swap128(res, cp.confirm_val);
302
303 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300304 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300305
306 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300307}
308
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300309static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300310{
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300311 struct hci_conn *hcon = conn->hcon;
312 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300313 int ret;
Vinicius Costa Gomes9b3d6742011-06-09 18:50:48 -0300314 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300315
316 swap128(skb->data, random);
317 skb_pull(skb, sizeof(random));
318
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300319 memset(hcon->ltk, 0, sizeof(hcon->ltk));
320
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300321 if (conn->hcon->out)
322 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
323 conn->src, conn->hcon->dst_type, conn->dst,
324 res);
325 else
326 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
327 conn->hcon->dst_type, conn->dst, 0, conn->src,
328 res);
329 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300330 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300331
332 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
333
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300334 swap128(res, confirm);
335
336 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300337 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300338 return SMP_CONFIRM_FAILED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300339 }
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300340
341 if (conn->hcon->out) {
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300342 __le16 ediv;
343 u8 rand[8];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300344
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300345 smp_s1(tfm, conn->tk, random, conn->prnd, key);
346 swap128(key, hcon->ltk);
347
348 memset(rand, 0, sizeof(rand));
349 ediv = 0;
350 hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300351 } else {
352 u8 r[16];
353
354 swap128(conn->prnd, r);
355 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
356
357 smp_s1(tfm, conn->tk, conn->prnd, random, key);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300358 swap128(key, hcon->ltk);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300359 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300360
361 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300362}
363
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300364static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300365{
366 struct smp_cmd_security_req *rp = (void *) skb->data;
367 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300368 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300369
370 BT_DBG("conn %p", conn);
371
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300372 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300373 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300374
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300375 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300376
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300377 memset(&cp, 0, sizeof(cp));
378 build_pairing_cmd(conn, &cp, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300379
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300380 conn->preq[0] = SMP_CMD_PAIRING_REQ;
381 memcpy(&conn->preq[1], &cp, sizeof(cp));
382
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300383 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300384
385 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300386
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300387 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300388}
389
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300390int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
391{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300392 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300393 __u8 authreq;
394
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300395 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
396
397 if (IS_ERR(hcon->hdev->tfm))
398 return 1;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300399
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300400 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
401 return 0;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300402
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300403 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300404 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300405
406 if (hcon->sec_level >= sec_level)
407 return 1;
408
409 authreq = seclevel_to_authreq(sec_level);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300410
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300411 if (hcon->link_mode & HCI_LM_MASTER) {
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300412 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300413
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300414 build_pairing_cmd(conn, &cp, authreq);
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300415 conn->preq[0] = SMP_CMD_PAIRING_REQ;
416 memcpy(&conn->preq[1], &cp, sizeof(cp));
417
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300418 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
419 } else {
420 struct smp_cmd_security_req cp;
421 cp.auth_req = authreq;
422 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
423 }
424
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300425 hcon->pending_sec_level = sec_level;
426 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
427
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300428 return 0;
429}
430
431int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
432{
433 __u8 code = skb->data[0];
434 __u8 reason;
435 int err = 0;
436
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300437 if (IS_ERR(conn->hcon->hdev->tfm)) {
438 err = PTR_ERR(conn->hcon->hdev->tfm);
439 reason = SMP_PAIRING_NOTSUPP;
440 goto done;
441 }
442
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300443 skb_pull(skb, sizeof(code));
444
445 switch (code) {
446 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300447 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300448 break;
449
450 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300451 reason = 0;
452 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300453 break;
454
455 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300456 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300457 break;
458
459 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300460 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300461 break;
462
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300463 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300464 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300465 break;
466
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300467 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300468 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300469 break;
470
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300471 case SMP_CMD_ENCRYPT_INFO:
472 case SMP_CMD_MASTER_IDENT:
473 case SMP_CMD_IDENT_INFO:
474 case SMP_CMD_IDENT_ADDR_INFO:
475 case SMP_CMD_SIGN_INFO:
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300476 default:
477 BT_DBG("Unknown command code 0x%2.2x", code);
478
479 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300480 err = -EOPNOTSUPP;
481 goto done;
482 }
483
484done:
485 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300486 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
487 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300488
489 kfree_skb(skb);
490 return err;
491}