1eb492e01SAnderson Briglia /* 2eb492e01SAnderson Briglia BlueZ - Bluetooth protocol stack for Linux 3eb492e01SAnderson Briglia Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4eb492e01SAnderson Briglia 5eb492e01SAnderson Briglia This program is free software; you can redistribute it and/or modify 6eb492e01SAnderson Briglia it under the terms of the GNU General Public License version 2 as 7eb492e01SAnderson Briglia published by the Free Software Foundation; 8eb492e01SAnderson Briglia 9eb492e01SAnderson Briglia THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10eb492e01SAnderson Briglia OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11eb492e01SAnderson Briglia FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 12eb492e01SAnderson Briglia IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 13eb492e01SAnderson Briglia CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 14eb492e01SAnderson Briglia WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15eb492e01SAnderson Briglia ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16eb492e01SAnderson Briglia OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17eb492e01SAnderson Briglia 18eb492e01SAnderson Briglia ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 19eb492e01SAnderson Briglia COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 20eb492e01SAnderson Briglia SOFTWARE IS DISCLAIMED. 21eb492e01SAnderson Briglia */ 22eb492e01SAnderson Briglia 23eb492e01SAnderson Briglia #include <net/bluetooth/bluetooth.h> 24eb492e01SAnderson Briglia #include <net/bluetooth/hci_core.h> 25eb492e01SAnderson Briglia #include <net/bluetooth/l2cap.h> 26eb492e01SAnderson Briglia #include <net/bluetooth/smp.h> 27d22ef0bcSAnderson Briglia #include <linux/crypto.h> 28f70490e6SStephen Rothwell #include <linux/scatterlist.h> 29d22ef0bcSAnderson Briglia #include <crypto/b128ops.h> 30d22ef0bcSAnderson Briglia 315d3de7dfSVinicius Costa Gomes #define SMP_TIMEOUT 30000 /* 30 seconds */ 325d3de7dfSVinicius Costa Gomes 33d22ef0bcSAnderson Briglia static inline void swap128(u8 src[16], u8 dst[16]) 34d22ef0bcSAnderson Briglia { 35d22ef0bcSAnderson Briglia int i; 36d22ef0bcSAnderson Briglia for (i = 0; i < 16; i++) 37d22ef0bcSAnderson Briglia dst[15 - i] = src[i]; 38d22ef0bcSAnderson Briglia } 39d22ef0bcSAnderson Briglia 40d22ef0bcSAnderson Briglia static inline void swap56(u8 src[7], u8 dst[7]) 41d22ef0bcSAnderson Briglia { 42d22ef0bcSAnderson Briglia int i; 43d22ef0bcSAnderson Briglia for (i = 0; i < 7; i++) 44d22ef0bcSAnderson Briglia dst[6 - i] = src[i]; 45d22ef0bcSAnderson Briglia } 46d22ef0bcSAnderson Briglia 47d22ef0bcSAnderson Briglia static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) 48d22ef0bcSAnderson Briglia { 49d22ef0bcSAnderson Briglia struct blkcipher_desc desc; 50d22ef0bcSAnderson Briglia struct scatterlist sg; 51d22ef0bcSAnderson Briglia int err, iv_len; 52d22ef0bcSAnderson Briglia unsigned char iv[128]; 53d22ef0bcSAnderson Briglia 54d22ef0bcSAnderson Briglia if (tfm == NULL) { 55d22ef0bcSAnderson Briglia BT_ERR("tfm %p", tfm); 56d22ef0bcSAnderson Briglia return -EINVAL; 57d22ef0bcSAnderson Briglia } 58d22ef0bcSAnderson Briglia 59d22ef0bcSAnderson Briglia desc.tfm = tfm; 60d22ef0bcSAnderson Briglia desc.flags = 0; 61d22ef0bcSAnderson Briglia 62d22ef0bcSAnderson Briglia err = crypto_blkcipher_setkey(tfm, k, 16); 63d22ef0bcSAnderson Briglia if (err) { 64d22ef0bcSAnderson Briglia BT_ERR("cipher setkey failed: %d", err); 65d22ef0bcSAnderson Briglia return err; 66d22ef0bcSAnderson Briglia } 67d22ef0bcSAnderson Briglia 68d22ef0bcSAnderson Briglia sg_init_one(&sg, r, 16); 69d22ef0bcSAnderson Briglia 70d22ef0bcSAnderson Briglia iv_len = crypto_blkcipher_ivsize(tfm); 71d22ef0bcSAnderson Briglia if (iv_len) { 72d22ef0bcSAnderson Briglia memset(&iv, 0xff, iv_len); 73d22ef0bcSAnderson Briglia crypto_blkcipher_set_iv(tfm, iv, iv_len); 74d22ef0bcSAnderson Briglia } 75d22ef0bcSAnderson Briglia 76d22ef0bcSAnderson Briglia err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); 77d22ef0bcSAnderson Briglia if (err) 78d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error %d", err); 79d22ef0bcSAnderson Briglia 80d22ef0bcSAnderson Briglia return err; 81d22ef0bcSAnderson Briglia } 82d22ef0bcSAnderson Briglia 83d22ef0bcSAnderson Briglia static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], 84d22ef0bcSAnderson Briglia u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, 85d22ef0bcSAnderson Briglia u8 _rat, bdaddr_t *ra, u8 res[16]) 86d22ef0bcSAnderson Briglia { 87d22ef0bcSAnderson Briglia u8 p1[16], p2[16]; 88d22ef0bcSAnderson Briglia int err; 89d22ef0bcSAnderson Briglia 90d22ef0bcSAnderson Briglia memset(p1, 0, 16); 91d22ef0bcSAnderson Briglia 92d22ef0bcSAnderson Briglia /* p1 = pres || preq || _rat || _iat */ 93d22ef0bcSAnderson Briglia swap56(pres, p1); 94d22ef0bcSAnderson Briglia swap56(preq, p1 + 7); 95d22ef0bcSAnderson Briglia p1[14] = _rat; 96d22ef0bcSAnderson Briglia p1[15] = _iat; 97d22ef0bcSAnderson Briglia 98d22ef0bcSAnderson Briglia memset(p2, 0, 16); 99d22ef0bcSAnderson Briglia 100d22ef0bcSAnderson Briglia /* p2 = padding || ia || ra */ 101d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 4), ia); 102d22ef0bcSAnderson Briglia baswap((bdaddr_t *) (p2 + 10), ra); 103d22ef0bcSAnderson Briglia 104d22ef0bcSAnderson Briglia /* res = r XOR p1 */ 105d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 106d22ef0bcSAnderson Briglia 107d22ef0bcSAnderson Briglia /* res = e(k, res) */ 108d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 109d22ef0bcSAnderson Briglia if (err) { 110d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 111d22ef0bcSAnderson Briglia return err; 112d22ef0bcSAnderson Briglia } 113d22ef0bcSAnderson Briglia 114d22ef0bcSAnderson Briglia /* res = res XOR p2 */ 115d22ef0bcSAnderson Briglia u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 116d22ef0bcSAnderson Briglia 117d22ef0bcSAnderson Briglia /* res = e(k, res) */ 118d22ef0bcSAnderson Briglia err = smp_e(tfm, k, res); 119d22ef0bcSAnderson Briglia if (err) 120d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 121d22ef0bcSAnderson Briglia 122d22ef0bcSAnderson Briglia return err; 123d22ef0bcSAnderson Briglia } 124d22ef0bcSAnderson Briglia 125d22ef0bcSAnderson Briglia static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], 126d22ef0bcSAnderson Briglia u8 r1[16], u8 r2[16], u8 _r[16]) 127d22ef0bcSAnderson Briglia { 128d22ef0bcSAnderson Briglia int err; 129d22ef0bcSAnderson Briglia 130d22ef0bcSAnderson Briglia /* Just least significant octets from r1 and r2 are considered */ 131d22ef0bcSAnderson Briglia memcpy(_r, r1 + 8, 8); 132d22ef0bcSAnderson Briglia memcpy(_r + 8, r2 + 8, 8); 133d22ef0bcSAnderson Briglia 134d22ef0bcSAnderson Briglia err = smp_e(tfm, k, _r); 135d22ef0bcSAnderson Briglia if (err) 136d22ef0bcSAnderson Briglia BT_ERR("Encrypt data error"); 137d22ef0bcSAnderson Briglia 138d22ef0bcSAnderson Briglia return err; 139d22ef0bcSAnderson Briglia } 140d22ef0bcSAnderson Briglia 141d22ef0bcSAnderson Briglia static int smp_rand(u8 *buf) 142d22ef0bcSAnderson Briglia { 143d22ef0bcSAnderson Briglia get_random_bytes(buf, 16); 144d22ef0bcSAnderson Briglia 145d22ef0bcSAnderson Briglia return 0; 146d22ef0bcSAnderson Briglia } 147eb492e01SAnderson Briglia 148eb492e01SAnderson Briglia static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, 149eb492e01SAnderson Briglia u16 dlen, void *data) 150eb492e01SAnderson Briglia { 151eb492e01SAnderson Briglia struct sk_buff *skb; 152eb492e01SAnderson Briglia struct l2cap_hdr *lh; 153eb492e01SAnderson Briglia int len; 154eb492e01SAnderson Briglia 155eb492e01SAnderson Briglia len = L2CAP_HDR_SIZE + sizeof(code) + dlen; 156eb492e01SAnderson Briglia 157eb492e01SAnderson Briglia if (len > conn->mtu) 158eb492e01SAnderson Briglia return NULL; 159eb492e01SAnderson Briglia 160eb492e01SAnderson Briglia skb = bt_skb_alloc(len, GFP_ATOMIC); 161eb492e01SAnderson Briglia if (!skb) 162eb492e01SAnderson Briglia return NULL; 163eb492e01SAnderson Briglia 164eb492e01SAnderson Briglia lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 165eb492e01SAnderson Briglia lh->len = cpu_to_le16(sizeof(code) + dlen); 166eb492e01SAnderson Briglia lh->cid = cpu_to_le16(L2CAP_CID_SMP); 167eb492e01SAnderson Briglia 168eb492e01SAnderson Briglia memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); 169eb492e01SAnderson Briglia 170eb492e01SAnderson Briglia memcpy(skb_put(skb, dlen), data, dlen); 171eb492e01SAnderson Briglia 172eb492e01SAnderson Briglia return skb; 173eb492e01SAnderson Briglia } 174eb492e01SAnderson Briglia 175eb492e01SAnderson Briglia static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 176eb492e01SAnderson Briglia { 177eb492e01SAnderson Briglia struct sk_buff *skb = smp_build_cmd(conn, code, len, data); 178eb492e01SAnderson Briglia 179eb492e01SAnderson Briglia BT_DBG("code 0x%2.2x", code); 180eb492e01SAnderson Briglia 181eb492e01SAnderson Briglia if (!skb) 182eb492e01SAnderson Briglia return; 183eb492e01SAnderson Briglia 184eb492e01SAnderson Briglia hci_send_acl(conn->hcon, skb, 0); 185e2dcd113SVinicius Costa Gomes 186e2dcd113SVinicius Costa Gomes mod_timer(&conn->security_timer, jiffies + 187e2dcd113SVinicius Costa Gomes msecs_to_jiffies(SMP_TIMEOUT)); 188eb492e01SAnderson Briglia } 189eb492e01SAnderson Briglia 190b8e66eacSVinicius Costa Gomes static void build_pairing_cmd(struct l2cap_conn *conn, 19154790f73SVinicius Costa Gomes struct smp_cmd_pairing *req, 19254790f73SVinicius Costa Gomes struct smp_cmd_pairing *rsp, 19354790f73SVinicius Costa Gomes __u8 authreq) 194b8e66eacSVinicius Costa Gomes { 19554790f73SVinicius Costa Gomes u8 dist_keys; 19654790f73SVinicius Costa Gomes 19754790f73SVinicius Costa Gomes dist_keys = 0; 19854790f73SVinicius Costa Gomes if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) { 199ca10b5eeSVinicius Costa Gomes dist_keys = SMP_DIST_ENC_KEY; 20054790f73SVinicius Costa Gomes authreq |= SMP_AUTH_BONDING; 20154790f73SVinicius Costa Gomes } 20254790f73SVinicius Costa Gomes 20354790f73SVinicius Costa Gomes if (rsp == NULL) { 20454790f73SVinicius Costa Gomes req->io_capability = conn->hcon->io_capability; 20554790f73SVinicius Costa Gomes req->oob_flag = SMP_OOB_NOT_PRESENT; 20654790f73SVinicius Costa Gomes req->max_key_size = SMP_MAX_ENC_KEY_SIZE; 20754790f73SVinicius Costa Gomes req->init_key_dist = dist_keys; 20854790f73SVinicius Costa Gomes req->resp_key_dist = dist_keys; 20954790f73SVinicius Costa Gomes req->auth_req = authreq; 21054790f73SVinicius Costa Gomes return; 21154790f73SVinicius Costa Gomes } 21254790f73SVinicius Costa Gomes 21354790f73SVinicius Costa Gomes rsp->io_capability = conn->hcon->io_capability; 21454790f73SVinicius Costa Gomes rsp->oob_flag = SMP_OOB_NOT_PRESENT; 21554790f73SVinicius Costa Gomes rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; 21654790f73SVinicius Costa Gomes rsp->init_key_dist = req->init_key_dist & dist_keys; 21754790f73SVinicius Costa Gomes rsp->resp_key_dist = req->resp_key_dist & dist_keys; 21854790f73SVinicius Costa Gomes rsp->auth_req = authreq; 219b8e66eacSVinicius Costa Gomes } 220b8e66eacSVinicius Costa Gomes 2213158c50cSVinicius Costa Gomes static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 2223158c50cSVinicius Costa Gomes { 2231c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 2241c1def09SVinicius Costa Gomes 2253158c50cSVinicius Costa Gomes if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || 2263158c50cSVinicius Costa Gomes (max_key_size < SMP_MIN_ENC_KEY_SIZE)) 2273158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 2283158c50cSVinicius Costa Gomes 2291c1def09SVinicius Costa Gomes smp->smp_key_size = max_key_size; 2303158c50cSVinicius Costa Gomes 2313158c50cSVinicius Costa Gomes return 0; 2323158c50cSVinicius Costa Gomes } 2333158c50cSVinicius Costa Gomes 2348aab4757SVinicius Costa Gomes static void confirm_work(struct work_struct *work) 2358aab4757SVinicius Costa Gomes { 2368aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, confirm); 2378aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 2388aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm; 2398aab4757SVinicius Costa Gomes struct smp_cmd_pairing_confirm cp; 2408aab4757SVinicius Costa Gomes int ret; 2418aab4757SVinicius Costa Gomes u8 res[16], reason; 2428aab4757SVinicius Costa Gomes 2438aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 2448aab4757SVinicius Costa Gomes 2458aab4757SVinicius Costa Gomes tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); 2468aab4757SVinicius Costa Gomes if (IS_ERR(tfm)) { 2478aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 2488aab4757SVinicius Costa Gomes goto error; 2498aab4757SVinicius Costa Gomes } 2508aab4757SVinicius Costa Gomes 2518aab4757SVinicius Costa Gomes smp->tfm = tfm; 2528aab4757SVinicius Costa Gomes 2538aab4757SVinicius Costa Gomes if (conn->hcon->out) 2548aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, 2558aab4757SVinicius Costa Gomes conn->src, conn->hcon->dst_type, conn->dst, 2568aab4757SVinicius Costa Gomes res); 2578aab4757SVinicius Costa Gomes else 2588aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 2598aab4757SVinicius Costa Gomes conn->hcon->dst_type, conn->dst, 0, conn->src, 2608aab4757SVinicius Costa Gomes res); 2618aab4757SVinicius Costa Gomes if (ret) { 2628aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 2638aab4757SVinicius Costa Gomes goto error; 2648aab4757SVinicius Costa Gomes } 2658aab4757SVinicius Costa Gomes 2668aab4757SVinicius Costa Gomes swap128(res, cp.confirm_val); 2678aab4757SVinicius Costa Gomes smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 2688aab4757SVinicius Costa Gomes 2698aab4757SVinicius Costa Gomes return; 2708aab4757SVinicius Costa Gomes 2718aab4757SVinicius Costa Gomes error: 2728aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); 2738aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 2748aab4757SVinicius Costa Gomes } 2758aab4757SVinicius Costa Gomes 2768aab4757SVinicius Costa Gomes static void random_work(struct work_struct *work) 2778aab4757SVinicius Costa Gomes { 2788aab4757SVinicius Costa Gomes struct smp_chan *smp = container_of(work, struct smp_chan, random); 2798aab4757SVinicius Costa Gomes struct l2cap_conn *conn = smp->conn; 2808aab4757SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 2818aab4757SVinicius Costa Gomes struct crypto_blkcipher *tfm = smp->tfm; 2828aab4757SVinicius Costa Gomes u8 reason, confirm[16], res[16], key[16]; 2838aab4757SVinicius Costa Gomes int ret; 2848aab4757SVinicius Costa Gomes 2858aab4757SVinicius Costa Gomes if (IS_ERR_OR_NULL(tfm)) { 2868aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 2878aab4757SVinicius Costa Gomes goto error; 2888aab4757SVinicius Costa Gomes } 2898aab4757SVinicius Costa Gomes 2908aab4757SVinicius Costa Gomes BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 2918aab4757SVinicius Costa Gomes 2928aab4757SVinicius Costa Gomes if (hcon->out) 2938aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, 2948aab4757SVinicius Costa Gomes conn->src, hcon->dst_type, conn->dst, 2958aab4757SVinicius Costa Gomes res); 2968aab4757SVinicius Costa Gomes else 2978aab4757SVinicius Costa Gomes ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 2988aab4757SVinicius Costa Gomes hcon->dst_type, conn->dst, 0, conn->src, 2998aab4757SVinicius Costa Gomes res); 3008aab4757SVinicius Costa Gomes if (ret) { 3018aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3028aab4757SVinicius Costa Gomes goto error; 3038aab4757SVinicius Costa Gomes } 3048aab4757SVinicius Costa Gomes 3058aab4757SVinicius Costa Gomes swap128(res, confirm); 3068aab4757SVinicius Costa Gomes 3078aab4757SVinicius Costa Gomes if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { 3088aab4757SVinicius Costa Gomes BT_ERR("Pairing failed (confirmation values mismatch)"); 3098aab4757SVinicius Costa Gomes reason = SMP_CONFIRM_FAILED; 3108aab4757SVinicius Costa Gomes goto error; 3118aab4757SVinicius Costa Gomes } 3128aab4757SVinicius Costa Gomes 3138aab4757SVinicius Costa Gomes if (hcon->out) { 3148aab4757SVinicius Costa Gomes u8 stk[16], rand[8]; 3158aab4757SVinicius Costa Gomes __le16 ediv; 3168aab4757SVinicius Costa Gomes 3178aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 3188aab4757SVinicius Costa Gomes ediv = 0; 3198aab4757SVinicius Costa Gomes 3208aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); 3218aab4757SVinicius Costa Gomes swap128(key, stk); 3228aab4757SVinicius Costa Gomes 3238aab4757SVinicius Costa Gomes memset(stk + smp->smp_key_size, 0, 3248aab4757SVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); 3258aab4757SVinicius Costa Gomes 3268aab4757SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) { 3278aab4757SVinicius Costa Gomes reason = SMP_UNSPECIFIED; 3288aab4757SVinicius Costa Gomes goto error; 3298aab4757SVinicius Costa Gomes } 3308aab4757SVinicius Costa Gomes 3318aab4757SVinicius Costa Gomes hci_le_start_enc(hcon, ediv, rand, stk); 3328aab4757SVinicius Costa Gomes hcon->enc_key_size = smp->smp_key_size; 3338aab4757SVinicius Costa Gomes } else { 3348aab4757SVinicius Costa Gomes u8 stk[16], r[16], rand[8]; 3358aab4757SVinicius Costa Gomes __le16 ediv; 3368aab4757SVinicius Costa Gomes 3378aab4757SVinicius Costa Gomes memset(rand, 0, sizeof(rand)); 3388aab4757SVinicius Costa Gomes ediv = 0; 3398aab4757SVinicius Costa Gomes 3408aab4757SVinicius Costa Gomes swap128(smp->prnd, r); 3418aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 3428aab4757SVinicius Costa Gomes 3438aab4757SVinicius Costa Gomes smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); 3448aab4757SVinicius Costa Gomes swap128(key, stk); 3458aab4757SVinicius Costa Gomes 3468aab4757SVinicius Costa Gomes memset(stk + smp->smp_key_size, 0, 3478aab4757SVinicius Costa Gomes SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); 3488aab4757SVinicius Costa Gomes 3498aab4757SVinicius Costa Gomes hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size, 3508aab4757SVinicius Costa Gomes ediv, rand, stk); 3518aab4757SVinicius Costa Gomes } 3528aab4757SVinicius Costa Gomes 3538aab4757SVinicius Costa Gomes return; 3548aab4757SVinicius Costa Gomes 3558aab4757SVinicius Costa Gomes error: 3568aab4757SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); 3578aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 3588aab4757SVinicius Costa Gomes } 3598aab4757SVinicius Costa Gomes 3608aab4757SVinicius Costa Gomes static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 3618aab4757SVinicius Costa Gomes { 3628aab4757SVinicius Costa Gomes struct smp_chan *smp; 3638aab4757SVinicius Costa Gomes 3648aab4757SVinicius Costa Gomes smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); 3658aab4757SVinicius Costa Gomes if (!smp) 3668aab4757SVinicius Costa Gomes return NULL; 3678aab4757SVinicius Costa Gomes 3688aab4757SVinicius Costa Gomes INIT_WORK(&smp->confirm, confirm_work); 3698aab4757SVinicius Costa Gomes INIT_WORK(&smp->random, random_work); 3708aab4757SVinicius Costa Gomes 3718aab4757SVinicius Costa Gomes smp->conn = conn; 3728aab4757SVinicius Costa Gomes conn->smp_chan = smp; 3738aab4757SVinicius Costa Gomes 3748aab4757SVinicius Costa Gomes hci_conn_hold(conn->hcon); 3758aab4757SVinicius Costa Gomes 3768aab4757SVinicius Costa Gomes return smp; 3778aab4757SVinicius Costa Gomes } 3788aab4757SVinicius Costa Gomes 3798aab4757SVinicius Costa Gomes void smp_chan_destroy(struct l2cap_conn *conn) 3808aab4757SVinicius Costa Gomes { 3818aab4757SVinicius Costa Gomes kfree(conn->smp_chan); 3828aab4757SVinicius Costa Gomes hci_conn_put(conn->hcon); 3838aab4757SVinicius Costa Gomes } 3848aab4757SVinicius Costa Gomes 385da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 38688ba43b6SAnderson Briglia { 3873158c50cSVinicius Costa Gomes struct smp_cmd_pairing rsp, *req = (void *) skb->data; 3888aab4757SVinicius Costa Gomes struct smp_chan *smp; 3893158c50cSVinicius Costa Gomes u8 key_size; 3908aab4757SVinicius Costa Gomes int ret; 39188ba43b6SAnderson Briglia 39288ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 39388ba43b6SAnderson Briglia 394d26a2345SVinicius Costa Gomes if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) 3958aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 3968aab4757SVinicius Costa Gomes 3978aab4757SVinicius Costa Gomes smp = conn->smp_chan; 398d26a2345SVinicius Costa Gomes 3991c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 4001c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], req, sizeof(*req)); 4013158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*req)); 40288ba43b6SAnderson Briglia 4033158c50cSVinicius Costa Gomes if (req->oob_flag) 404da85e5e5SVinicius Costa Gomes return SMP_OOB_NOT_AVAIL; 405da85e5e5SVinicius Costa Gomes 406da85e5e5SVinicius Costa Gomes /* We didn't start the pairing, so no requirements */ 40754790f73SVinicius Costa Gomes build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE); 4083158c50cSVinicius Costa Gomes 4093158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp.max_key_size); 4103158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 4113158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 41288ba43b6SAnderson Briglia 4137d24ddccSAnderson Briglia /* Just works */ 4141c1def09SVinicius Costa Gomes memset(smp->tk, 0, sizeof(smp->tk)); 4157d24ddccSAnderson Briglia 4168aab4757SVinicius Costa Gomes ret = smp_rand(smp->prnd); 4178aab4757SVinicius Costa Gomes if (ret) 4188aab4757SVinicius Costa Gomes return SMP_UNSPECIFIED; 4198aab4757SVinicius Costa Gomes 4201c1def09SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 4211c1def09SVinicius Costa Gomes memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 422f01ead31SAnderson Briglia 4233158c50cSVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 424da85e5e5SVinicius Costa Gomes 425da85e5e5SVinicius Costa Gomes return 0; 42688ba43b6SAnderson Briglia } 42788ba43b6SAnderson Briglia 428da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 42988ba43b6SAnderson Briglia { 4303158c50cSVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 4311c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 4328aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 4338aab4757SVinicius Costa Gomes u8 key_size; 4347d24ddccSAnderson Briglia int ret; 43588ba43b6SAnderson Briglia 43688ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 43788ba43b6SAnderson Briglia 4383158c50cSVinicius Costa Gomes skb_pull(skb, sizeof(*rsp)); 439da85e5e5SVinicius Costa Gomes 4401c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 4413158c50cSVinicius Costa Gomes 4423158c50cSVinicius Costa Gomes key_size = min(req->max_key_size, rsp->max_key_size); 4433158c50cSVinicius Costa Gomes if (check_enc_key_size(conn, key_size)) 4443158c50cSVinicius Costa Gomes return SMP_ENC_KEY_SIZE; 4453158c50cSVinicius Costa Gomes 4463158c50cSVinicius Costa Gomes if (rsp->oob_flag) 447da85e5e5SVinicius Costa Gomes return SMP_OOB_NOT_AVAIL; 448da85e5e5SVinicius Costa Gomes 4497d24ddccSAnderson Briglia /* Just works */ 4501c1def09SVinicius Costa Gomes memset(smp->tk, 0, sizeof(smp->tk)); 45188ba43b6SAnderson Briglia 4521c1def09SVinicius Costa Gomes ret = smp_rand(smp->prnd); 4537d24ddccSAnderson Briglia if (ret) 454da85e5e5SVinicius Costa Gomes return SMP_UNSPECIFIED; 4557d24ddccSAnderson Briglia 4568aab4757SVinicius Costa Gomes smp->prsp[0] = SMP_CMD_PAIRING_RSP; 4578aab4757SVinicius Costa Gomes memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 4587d24ddccSAnderson Briglia 4598aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 460da85e5e5SVinicius Costa Gomes 461da85e5e5SVinicius Costa Gomes return 0; 46288ba43b6SAnderson Briglia } 46388ba43b6SAnderson Briglia 464da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 46588ba43b6SAnderson Briglia { 4661c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 4678aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 4687d24ddccSAnderson Briglia 46988ba43b6SAnderson Briglia BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 47088ba43b6SAnderson Briglia 4711c1def09SVinicius Costa Gomes memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 4721c1def09SVinicius Costa Gomes skb_pull(skb, sizeof(smp->pcnf)); 4737d24ddccSAnderson Briglia 47488ba43b6SAnderson Briglia if (conn->hcon->out) { 4757d24ddccSAnderson Briglia u8 random[16]; 47688ba43b6SAnderson Briglia 4771c1def09SVinicius Costa Gomes swap128(smp->prnd, random); 47888ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 4797d24ddccSAnderson Briglia random); 48088ba43b6SAnderson Briglia } else { 4818aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->confirm); 48288ba43b6SAnderson Briglia } 483da85e5e5SVinicius Costa Gomes 484da85e5e5SVinicius Costa Gomes return 0; 48588ba43b6SAnderson Briglia } 48688ba43b6SAnderson Briglia 487da85e5e5SVinicius Costa Gomes static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 48888ba43b6SAnderson Briglia { 4891c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 4908aab4757SVinicius Costa Gomes struct hci_dev *hdev = conn->hcon->hdev; 4917d24ddccSAnderson Briglia 4928aab4757SVinicius Costa Gomes BT_DBG("conn %p", conn); 4937d24ddccSAnderson Briglia 4948aab4757SVinicius Costa Gomes swap128(skb->data, smp->rrnd); 4958aab4757SVinicius Costa Gomes skb_pull(skb, sizeof(smp->rrnd)); 49688ba43b6SAnderson Briglia 4978aab4757SVinicius Costa Gomes queue_work(hdev->workqueue, &smp->random); 498da85e5e5SVinicius Costa Gomes 499da85e5e5SVinicius Costa Gomes return 0; 50088ba43b6SAnderson Briglia } 50188ba43b6SAnderson Briglia 502988c5997SVinicius Costa Gomes static u8 smp_ltk_encrypt(struct l2cap_conn *conn) 503988c5997SVinicius Costa Gomes { 504988c5997SVinicius Costa Gomes struct link_key *key; 505988c5997SVinicius Costa Gomes struct key_master_id *master; 506988c5997SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 507988c5997SVinicius Costa Gomes 508988c5997SVinicius Costa Gomes key = hci_find_link_key_type(hcon->hdev, conn->dst, 509988c5997SVinicius Costa Gomes HCI_LK_SMP_LTK); 510988c5997SVinicius Costa Gomes if (!key) 511988c5997SVinicius Costa Gomes return 0; 512988c5997SVinicius Costa Gomes 513988c5997SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, 514988c5997SVinicius Costa Gomes &hcon->pend)) 515988c5997SVinicius Costa Gomes return 1; 516988c5997SVinicius Costa Gomes 517988c5997SVinicius Costa Gomes master = (void *) key->data; 518988c5997SVinicius Costa Gomes hci_le_start_enc(hcon, master->ediv, master->rand, 519988c5997SVinicius Costa Gomes key->val); 520988c5997SVinicius Costa Gomes hcon->enc_key_size = key->pin_len; 521988c5997SVinicius Costa Gomes 522988c5997SVinicius Costa Gomes return 1; 523988c5997SVinicius Costa Gomes 524988c5997SVinicius Costa Gomes } 525da85e5e5SVinicius Costa Gomes static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 52688ba43b6SAnderson Briglia { 52788ba43b6SAnderson Briglia struct smp_cmd_security_req *rp = (void *) skb->data; 52888ba43b6SAnderson Briglia struct smp_cmd_pairing cp; 529f1cb9af5SVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 5308aab4757SVinicius Costa Gomes struct smp_chan *smp; 53188ba43b6SAnderson Briglia 53288ba43b6SAnderson Briglia BT_DBG("conn %p", conn); 53388ba43b6SAnderson Briglia 534feb45eb5SVinicius Costa Gomes hcon->pending_sec_level = BT_SECURITY_MEDIUM; 535feb45eb5SVinicius Costa Gomes 536988c5997SVinicius Costa Gomes if (smp_ltk_encrypt(conn)) 537988c5997SVinicius Costa Gomes return 0; 538988c5997SVinicius Costa Gomes 539d26a2345SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) 540da85e5e5SVinicius Costa Gomes return 0; 541f1cb9af5SVinicius Costa Gomes 5428aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 543d26a2345SVinicius Costa Gomes 54488ba43b6SAnderson Briglia skb_pull(skb, sizeof(*rp)); 54588ba43b6SAnderson Briglia 546da85e5e5SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 54754790f73SVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, rp->auth_req); 54888ba43b6SAnderson Briglia 5491c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5501c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 551f01ead31SAnderson Briglia 55288ba43b6SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 553f1cb9af5SVinicius Costa Gomes 554da85e5e5SVinicius Costa Gomes return 0; 55588ba43b6SAnderson Briglia } 55688ba43b6SAnderson Briglia 557eb492e01SAnderson Briglia int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) 558eb492e01SAnderson Briglia { 5593a0259bbSVinicius Costa Gomes struct hci_conn *hcon = conn->hcon; 5601c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 561eb492e01SAnderson Briglia 5623a0259bbSVinicius Costa Gomes BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); 5633a0259bbSVinicius Costa Gomes 5642e65c9d2SAndre Guedes if (!lmp_host_le_capable(hcon->hdev)) 5652e65c9d2SAndre Guedes return 1; 5662e65c9d2SAndre Guedes 567f1cb9af5SVinicius Costa Gomes if (sec_level == BT_SECURITY_LOW) 568eb492e01SAnderson Briglia return 1; 569f1cb9af5SVinicius Costa Gomes 570f1cb9af5SVinicius Costa Gomes if (hcon->sec_level >= sec_level) 571f1cb9af5SVinicius Costa Gomes return 1; 572f1cb9af5SVinicius Costa Gomes 573988c5997SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) 574988c5997SVinicius Costa Gomes if (smp_ltk_encrypt(conn)) 575d26a2345SVinicius Costa Gomes goto done; 576d26a2345SVinicius Costa Gomes 577d26a2345SVinicius Costa Gomes if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) 578d26a2345SVinicius Costa Gomes return 0; 579d26a2345SVinicius Costa Gomes 5808aab4757SVinicius Costa Gomes smp = smp_chan_create(conn); 581d26a2345SVinicius Costa Gomes 582d26a2345SVinicius Costa Gomes if (hcon->link_mode & HCI_LM_MASTER) { 583d26a2345SVinicius Costa Gomes struct smp_cmd_pairing cp; 584f01ead31SAnderson Briglia 5850fb4eb6fSVinicius Costa Gomes build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE); 5861c1def09SVinicius Costa Gomes smp->preq[0] = SMP_CMD_PAIRING_REQ; 5871c1def09SVinicius Costa Gomes memcpy(&smp->preq[1], &cp, sizeof(cp)); 588f01ead31SAnderson Briglia 589eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 590eb492e01SAnderson Briglia } else { 591eb492e01SAnderson Briglia struct smp_cmd_security_req cp; 5920fb4eb6fSVinicius Costa Gomes cp.auth_req = SMP_AUTH_NONE; 593eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 594eb492e01SAnderson Briglia } 595eb492e01SAnderson Briglia 59602bc7455SVinicius Costa Gomes done: 597f1cb9af5SVinicius Costa Gomes hcon->pending_sec_level = sec_level; 598f1cb9af5SVinicius Costa Gomes 599eb492e01SAnderson Briglia return 0; 600eb492e01SAnderson Briglia } 601eb492e01SAnderson Briglia 6027034b911SVinicius Costa Gomes static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 6037034b911SVinicius Costa Gomes { 60416b90839SVinicius Costa Gomes struct smp_cmd_encrypt_info *rp = (void *) skb->data; 6051c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 60616b90839SVinicius Costa Gomes 60716b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 60816b90839SVinicius Costa Gomes 6091c1def09SVinicius Costa Gomes memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 61016b90839SVinicius Costa Gomes 6117034b911SVinicius Costa Gomes return 0; 6127034b911SVinicius Costa Gomes } 6137034b911SVinicius Costa Gomes 6147034b911SVinicius Costa Gomes static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) 6157034b911SVinicius Costa Gomes { 61616b90839SVinicius Costa Gomes struct smp_cmd_master_ident *rp = (void *) skb->data; 6171c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 6187034b911SVinicius Costa Gomes 61916b90839SVinicius Costa Gomes skb_pull(skb, sizeof(*rp)); 62016b90839SVinicius Costa Gomes 6211c1def09SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size, 6221c1def09SVinicius Costa Gomes rp->ediv, rp->rand, smp->tk); 6237034b911SVinicius Costa Gomes 6247034b911SVinicius Costa Gomes smp_distribute_keys(conn, 1); 6257034b911SVinicius Costa Gomes 6267034b911SVinicius Costa Gomes return 0; 6277034b911SVinicius Costa Gomes } 6287034b911SVinicius Costa Gomes 629eb492e01SAnderson Briglia int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 630eb492e01SAnderson Briglia { 631eb492e01SAnderson Briglia __u8 code = skb->data[0]; 632eb492e01SAnderson Briglia __u8 reason; 633eb492e01SAnderson Briglia int err = 0; 634eb492e01SAnderson Briglia 6352e65c9d2SAndre Guedes if (!lmp_host_le_capable(conn->hcon->hdev)) { 6362e65c9d2SAndre Guedes err = -ENOTSUPP; 6372e65c9d2SAndre Guedes reason = SMP_PAIRING_NOTSUPP; 6382e65c9d2SAndre Guedes goto done; 6392e65c9d2SAndre Guedes } 6402e65c9d2SAndre Guedes 641eb492e01SAnderson Briglia skb_pull(skb, sizeof(code)); 642eb492e01SAnderson Briglia 643eb492e01SAnderson Briglia switch (code) { 644eb492e01SAnderson Briglia case SMP_CMD_PAIRING_REQ: 645da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_req(conn, skb); 646eb492e01SAnderson Briglia break; 647eb492e01SAnderson Briglia 648eb492e01SAnderson Briglia case SMP_CMD_PAIRING_FAIL: 649da85e5e5SVinicius Costa Gomes reason = 0; 650da85e5e5SVinicius Costa Gomes err = -EPERM; 651eb492e01SAnderson Briglia break; 652eb492e01SAnderson Briglia 653eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RSP: 654da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_rsp(conn, skb); 65588ba43b6SAnderson Briglia break; 65688ba43b6SAnderson Briglia 65788ba43b6SAnderson Briglia case SMP_CMD_SECURITY_REQ: 658da85e5e5SVinicius Costa Gomes reason = smp_cmd_security_req(conn, skb); 65988ba43b6SAnderson Briglia break; 66088ba43b6SAnderson Briglia 661eb492e01SAnderson Briglia case SMP_CMD_PAIRING_CONFIRM: 662da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_confirm(conn, skb); 66388ba43b6SAnderson Briglia break; 66488ba43b6SAnderson Briglia 665eb492e01SAnderson Briglia case SMP_CMD_PAIRING_RANDOM: 666da85e5e5SVinicius Costa Gomes reason = smp_cmd_pairing_random(conn, skb); 66788ba43b6SAnderson Briglia break; 66888ba43b6SAnderson Briglia 669eb492e01SAnderson Briglia case SMP_CMD_ENCRYPT_INFO: 6707034b911SVinicius Costa Gomes reason = smp_cmd_encrypt_info(conn, skb); 6717034b911SVinicius Costa Gomes break; 6727034b911SVinicius Costa Gomes 673eb492e01SAnderson Briglia case SMP_CMD_MASTER_IDENT: 6747034b911SVinicius Costa Gomes reason = smp_cmd_master_ident(conn, skb); 6757034b911SVinicius Costa Gomes break; 6767034b911SVinicius Costa Gomes 677eb492e01SAnderson Briglia case SMP_CMD_IDENT_INFO: 678eb492e01SAnderson Briglia case SMP_CMD_IDENT_ADDR_INFO: 679eb492e01SAnderson Briglia case SMP_CMD_SIGN_INFO: 6807034b911SVinicius Costa Gomes /* Just ignored */ 6817034b911SVinicius Costa Gomes reason = 0; 6827034b911SVinicius Costa Gomes break; 6837034b911SVinicius Costa Gomes 684eb492e01SAnderson Briglia default: 685eb492e01SAnderson Briglia BT_DBG("Unknown command code 0x%2.2x", code); 686eb492e01SAnderson Briglia 687eb492e01SAnderson Briglia reason = SMP_CMD_NOTSUPP; 6883a0259bbSVinicius Costa Gomes err = -EOPNOTSUPP; 6893a0259bbSVinicius Costa Gomes goto done; 6903a0259bbSVinicius Costa Gomes } 6913a0259bbSVinicius Costa Gomes 6923a0259bbSVinicius Costa Gomes done: 6933a0259bbSVinicius Costa Gomes if (reason) 694eb492e01SAnderson Briglia smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 695eb492e01SAnderson Briglia &reason); 696eb492e01SAnderson Briglia 697eb492e01SAnderson Briglia kfree_skb(skb); 698eb492e01SAnderson Briglia return err; 699eb492e01SAnderson Briglia } 7007034b911SVinicius Costa Gomes 7017034b911SVinicius Costa Gomes int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) 7027034b911SVinicius Costa Gomes { 7037034b911SVinicius Costa Gomes struct smp_cmd_pairing *req, *rsp; 7041c1def09SVinicius Costa Gomes struct smp_chan *smp = conn->smp_chan; 7057034b911SVinicius Costa Gomes __u8 *keydist; 7067034b911SVinicius Costa Gomes 7077034b911SVinicius Costa Gomes BT_DBG("conn %p force %d", conn, force); 7087034b911SVinicius Costa Gomes 709d26a2345SVinicius Costa Gomes if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) 710d26a2345SVinicius Costa Gomes return 0; 711d26a2345SVinicius Costa Gomes 7121c1def09SVinicius Costa Gomes rsp = (void *) &smp->prsp[1]; 7137034b911SVinicius Costa Gomes 7147034b911SVinicius Costa Gomes /* The responder sends its keys first */ 7157034b911SVinicius Costa Gomes if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) 7167034b911SVinicius Costa Gomes return 0; 7177034b911SVinicius Costa Gomes 7181c1def09SVinicius Costa Gomes req = (void *) &smp->preq[1]; 7197034b911SVinicius Costa Gomes 7207034b911SVinicius Costa Gomes if (conn->hcon->out) { 7217034b911SVinicius Costa Gomes keydist = &rsp->init_key_dist; 7227034b911SVinicius Costa Gomes *keydist &= req->init_key_dist; 7237034b911SVinicius Costa Gomes } else { 7247034b911SVinicius Costa Gomes keydist = &rsp->resp_key_dist; 7257034b911SVinicius Costa Gomes *keydist &= req->resp_key_dist; 7267034b911SVinicius Costa Gomes } 7277034b911SVinicius Costa Gomes 7287034b911SVinicius Costa Gomes 7297034b911SVinicius Costa Gomes BT_DBG("keydist 0x%x", *keydist); 7307034b911SVinicius Costa Gomes 7317034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ENC_KEY) { 7327034b911SVinicius Costa Gomes struct smp_cmd_encrypt_info enc; 7337034b911SVinicius Costa Gomes struct smp_cmd_master_ident ident; 7347034b911SVinicius Costa Gomes __le16 ediv; 7357034b911SVinicius Costa Gomes 7367034b911SVinicius Costa Gomes get_random_bytes(enc.ltk, sizeof(enc.ltk)); 7377034b911SVinicius Costa Gomes get_random_bytes(&ediv, sizeof(ediv)); 7387034b911SVinicius Costa Gomes get_random_bytes(ident.rand, sizeof(ident.rand)); 7397034b911SVinicius Costa Gomes 7407034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 7417034b911SVinicius Costa Gomes 7421c1def09SVinicius Costa Gomes hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size, 743726b4ffcSVinicius Costa Gomes ediv, ident.rand, enc.ltk); 74416b90839SVinicius Costa Gomes 7457034b911SVinicius Costa Gomes ident.ediv = cpu_to_le16(ediv); 7467034b911SVinicius Costa Gomes 7477034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); 7487034b911SVinicius Costa Gomes 7497034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ENC_KEY; 7507034b911SVinicius Costa Gomes } 7517034b911SVinicius Costa Gomes 7527034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_ID_KEY) { 7537034b911SVinicius Costa Gomes struct smp_cmd_ident_addr_info addrinfo; 7547034b911SVinicius Costa Gomes struct smp_cmd_ident_info idinfo; 7557034b911SVinicius Costa Gomes 7567034b911SVinicius Costa Gomes /* Send a dummy key */ 7577034b911SVinicius Costa Gomes get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); 7587034b911SVinicius Costa Gomes 7597034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 7607034b911SVinicius Costa Gomes 7617034b911SVinicius Costa Gomes /* Just public address */ 7627034b911SVinicius Costa Gomes memset(&addrinfo, 0, sizeof(addrinfo)); 7637034b911SVinicius Costa Gomes bacpy(&addrinfo.bdaddr, conn->src); 7647034b911SVinicius Costa Gomes 7657034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 7667034b911SVinicius Costa Gomes &addrinfo); 7677034b911SVinicius Costa Gomes 7687034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_ID_KEY; 7697034b911SVinicius Costa Gomes } 7707034b911SVinicius Costa Gomes 7717034b911SVinicius Costa Gomes if (*keydist & SMP_DIST_SIGN) { 7727034b911SVinicius Costa Gomes struct smp_cmd_sign_info sign; 7737034b911SVinicius Costa Gomes 7747034b911SVinicius Costa Gomes /* Send a dummy key */ 7757034b911SVinicius Costa Gomes get_random_bytes(sign.csrk, sizeof(sign.csrk)); 7767034b911SVinicius Costa Gomes 7777034b911SVinicius Costa Gomes smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 7787034b911SVinicius Costa Gomes 7797034b911SVinicius Costa Gomes *keydist &= ~SMP_DIST_SIGN; 7807034b911SVinicius Costa Gomes } 7817034b911SVinicius Costa Gomes 782d26a2345SVinicius Costa Gomes if (conn->hcon->out || force) { 783d26a2345SVinicius Costa Gomes clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); 784d26a2345SVinicius Costa Gomes del_timer(&conn->security_timer); 7858aab4757SVinicius Costa Gomes smp_chan_destroy(conn); 786d26a2345SVinicius Costa Gomes } 787d26a2345SVinicius Costa Gomes 7887034b911SVinicius Costa Gomes return 0; 7897034b911SVinicius Costa Gomes } 790