18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci BlueZ - Bluetooth protocol stack for Linux 38c2ecf20Sopenharmony_ci Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 68c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License version 2 as 78c2ecf20Sopenharmony_ci published by the Free Software Foundation; 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 108c2ecf20Sopenharmony_ci OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 118c2ecf20Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 128c2ecf20Sopenharmony_ci IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 138c2ecf20Sopenharmony_ci CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 148c2ecf20Sopenharmony_ci WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 158c2ecf20Sopenharmony_ci ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 168c2ecf20Sopenharmony_ci OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 198c2ecf20Sopenharmony_ci COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 208c2ecf20Sopenharmony_ci SOFTWARE IS DISCLAIMED. 218c2ecf20Sopenharmony_ci*/ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 248c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 258c2ecf20Sopenharmony_ci#include <linux/crypto.h> 268c2ecf20Sopenharmony_ci#include <crypto/aes.h> 278c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 288c2ecf20Sopenharmony_ci#include <crypto/b128ops.h> 298c2ecf20Sopenharmony_ci#include <crypto/hash.h> 308c2ecf20Sopenharmony_ci#include <crypto/kpp.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 338c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h> 348c2ecf20Sopenharmony_ci#include <net/bluetooth/l2cap.h> 358c2ecf20Sopenharmony_ci#include <net/bluetooth/mgmt.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "ecdh_helper.h" 388c2ecf20Sopenharmony_ci#include "smp.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define SMP_DEV(hdev) \ 418c2ecf20Sopenharmony_ci ((struct smp_dev *)((struct l2cap_chan *)((hdev)->smp_data))->data) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* Low-level debug macros to be used for stuff that we don't want 448c2ecf20Sopenharmony_ci * accidentially in dmesg, i.e. the values of the various crypto keys 458c2ecf20Sopenharmony_ci * and the inputs & outputs of crypto functions. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci#ifdef DEBUG 488c2ecf20Sopenharmony_ci#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \ 498c2ecf20Sopenharmony_ci ##__VA_ARGS__) 508c2ecf20Sopenharmony_ci#else 518c2ecf20Sopenharmony_ci#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \ 528c2ecf20Sopenharmony_ci ##__VA_ARGS__) 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* Keys which are not distributed with Secure Connections */ 588c2ecf20Sopenharmony_ci#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define SMP_TIMEOUT msecs_to_jiffies(30000) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define AUTH_REQ_MASK(dev) (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \ 638c2ecf20Sopenharmony_ci 0x3f : 0x07) 648c2ecf20Sopenharmony_ci#define KEY_DIST_MASK 0x07 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* Maximum message length that can be passed to aes_cmac */ 678c2ecf20Sopenharmony_ci#define CMAC_MSG_MAX 80 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cienum { 708c2ecf20Sopenharmony_ci SMP_FLAG_TK_VALID, 718c2ecf20Sopenharmony_ci SMP_FLAG_CFM_PENDING, 728c2ecf20Sopenharmony_ci SMP_FLAG_MITM_AUTH, 738c2ecf20Sopenharmony_ci SMP_FLAG_COMPLETE, 748c2ecf20Sopenharmony_ci SMP_FLAG_INITIATOR, 758c2ecf20Sopenharmony_ci SMP_FLAG_SC, 768c2ecf20Sopenharmony_ci SMP_FLAG_REMOTE_PK, 778c2ecf20Sopenharmony_ci SMP_FLAG_DEBUG_KEY, 788c2ecf20Sopenharmony_ci SMP_FLAG_WAIT_USER, 798c2ecf20Sopenharmony_ci SMP_FLAG_DHKEY_PENDING, 808c2ecf20Sopenharmony_ci SMP_FLAG_REMOTE_OOB, 818c2ecf20Sopenharmony_ci SMP_FLAG_LOCAL_OOB, 828c2ecf20Sopenharmony_ci SMP_FLAG_CT2, 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct smp_dev { 868c2ecf20Sopenharmony_ci /* Secure Connections OOB data */ 878c2ecf20Sopenharmony_ci bool local_oob; 888c2ecf20Sopenharmony_ci u8 local_pk[64]; 898c2ecf20Sopenharmony_ci u8 local_rand[16]; 908c2ecf20Sopenharmony_ci bool debug_key; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci struct crypto_shash *tfm_cmac; 938c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh; 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistruct smp_chan { 978c2ecf20Sopenharmony_ci struct l2cap_conn *conn; 988c2ecf20Sopenharmony_ci struct delayed_work security_timer; 998c2ecf20Sopenharmony_ci unsigned long allow_cmd; /* Bitmask of allowed commands */ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci u8 preq[7]; /* SMP Pairing Request */ 1028c2ecf20Sopenharmony_ci u8 prsp[7]; /* SMP Pairing Response */ 1038c2ecf20Sopenharmony_ci u8 prnd[16]; /* SMP Pairing Random (local) */ 1048c2ecf20Sopenharmony_ci u8 rrnd[16]; /* SMP Pairing Random (remote) */ 1058c2ecf20Sopenharmony_ci u8 pcnf[16]; /* SMP Pairing Confirm */ 1068c2ecf20Sopenharmony_ci u8 tk[16]; /* SMP Temporary Key */ 1078c2ecf20Sopenharmony_ci u8 rr[16]; /* Remote OOB ra/rb value */ 1088c2ecf20Sopenharmony_ci u8 lr[16]; /* Local OOB ra/rb value */ 1098c2ecf20Sopenharmony_ci u8 enc_key_size; 1108c2ecf20Sopenharmony_ci u8 remote_key_dist; 1118c2ecf20Sopenharmony_ci bdaddr_t id_addr; 1128c2ecf20Sopenharmony_ci u8 id_addr_type; 1138c2ecf20Sopenharmony_ci u8 irk[16]; 1148c2ecf20Sopenharmony_ci struct smp_csrk *csrk; 1158c2ecf20Sopenharmony_ci struct smp_csrk *responder_csrk; 1168c2ecf20Sopenharmony_ci struct smp_ltk *ltk; 1178c2ecf20Sopenharmony_ci struct smp_ltk *responder_ltk; 1188c2ecf20Sopenharmony_ci struct smp_irk *remote_irk; 1198c2ecf20Sopenharmony_ci u8 *link_key; 1208c2ecf20Sopenharmony_ci unsigned long flags; 1218c2ecf20Sopenharmony_ci u8 method; 1228c2ecf20Sopenharmony_ci u8 passkey_round; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Secure Connections variables */ 1258c2ecf20Sopenharmony_ci u8 local_pk[64]; 1268c2ecf20Sopenharmony_ci u8 remote_pk[64]; 1278c2ecf20Sopenharmony_ci u8 dhkey[32]; 1288c2ecf20Sopenharmony_ci u8 mackey[16]; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci struct crypto_shash *tfm_cmac; 1318c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh; 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* These debug key values are defined in the SMP section of the core 1358c2ecf20Sopenharmony_ci * specification. debug_pk is the public debug key and debug_sk the 1368c2ecf20Sopenharmony_ci * private debug key. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_cistatic const u8 debug_pk[64] = { 1398c2ecf20Sopenharmony_ci 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 1408c2ecf20Sopenharmony_ci 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 1418c2ecf20Sopenharmony_ci 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, 1428c2ecf20Sopenharmony_ci 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74, 1458c2ecf20Sopenharmony_ci 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76, 1468c2ecf20Sopenharmony_ci 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 1478c2ecf20Sopenharmony_ci 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc, 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic const u8 debug_sk[32] = { 1518c2ecf20Sopenharmony_ci 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58, 1528c2ecf20Sopenharmony_ci 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a, 1538c2ecf20Sopenharmony_ci 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74, 1548c2ecf20Sopenharmony_ci 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f, 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic inline void swap_buf(const u8 *src, u8 *dst, size_t len) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci size_t i; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 1628c2ecf20Sopenharmony_ci dst[len - 1 - i] = src[i]; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* The following functions map to the LE SC SMP crypto functions 1668c2ecf20Sopenharmony_ci * AES-CMAC, f4, f5, f6, g2 and h6. 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int aes_cmac(struct crypto_shash *tfm, const u8 k[16], const u8 *m, 1708c2ecf20Sopenharmony_ci size_t len, u8 mac[16]) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX]; 1738c2ecf20Sopenharmony_ci int err; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (len > CMAC_MSG_MAX) 1768c2ecf20Sopenharmony_ci return -EFBIG; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!tfm) { 1798c2ecf20Sopenharmony_ci BT_ERR("tfm %p", tfm); 1808c2ecf20Sopenharmony_ci return -EINVAL; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* Swap key and message from LSB to MSB */ 1848c2ecf20Sopenharmony_ci swap_buf(k, tmp, 16); 1858c2ecf20Sopenharmony_ci swap_buf(m, msg_msb, len); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci SMP_DBG("msg (len %zu) %*phN", len, (int) len, m); 1888c2ecf20Sopenharmony_ci SMP_DBG("key %16phN", k); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci err = crypto_shash_setkey(tfm, tmp, 16); 1918c2ecf20Sopenharmony_ci if (err) { 1928c2ecf20Sopenharmony_ci BT_ERR("cipher setkey failed: %d", err); 1938c2ecf20Sopenharmony_ci return err; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci err = crypto_shash_tfm_digest(tfm, msg_msb, len, mac_msb); 1978c2ecf20Sopenharmony_ci if (err) { 1988c2ecf20Sopenharmony_ci BT_ERR("Hash computation error %d", err); 1998c2ecf20Sopenharmony_ci return err; 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci swap_buf(mac_msb, mac, 16); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci SMP_DBG("mac %16phN", mac); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int smp_f4(struct crypto_shash *tfm_cmac, const u8 u[32], 2108c2ecf20Sopenharmony_ci const u8 v[32], const u8 x[16], u8 z, u8 res[16]) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci u8 m[65]; 2138c2ecf20Sopenharmony_ci int err; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci SMP_DBG("u %32phN", u); 2168c2ecf20Sopenharmony_ci SMP_DBG("v %32phN", v); 2178c2ecf20Sopenharmony_ci SMP_DBG("x %16phN z %02x", x, z); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci m[0] = z; 2208c2ecf20Sopenharmony_ci memcpy(m + 1, v, 32); 2218c2ecf20Sopenharmony_ci memcpy(m + 33, u, 32); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, x, m, sizeof(m), res); 2248c2ecf20Sopenharmony_ci if (err) 2258c2ecf20Sopenharmony_ci return err; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci SMP_DBG("res %16phN", res); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return err; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic int smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32], 2338c2ecf20Sopenharmony_ci const u8 n1[16], const u8 n2[16], const u8 a1[7], 2348c2ecf20Sopenharmony_ci const u8 a2[7], u8 mackey[16], u8 ltk[16]) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci /* The btle, salt and length "magic" values are as defined in 2378c2ecf20Sopenharmony_ci * the SMP section of the Bluetooth core specification. In ASCII 2388c2ecf20Sopenharmony_ci * the btle value ends up being 'btle'. The salt is just a 2398c2ecf20Sopenharmony_ci * random number whereas length is the value 256 in little 2408c2ecf20Sopenharmony_ci * endian format. 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 }; 2438c2ecf20Sopenharmony_ci const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60, 2448c2ecf20Sopenharmony_ci 0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c }; 2458c2ecf20Sopenharmony_ci const u8 length[2] = { 0x00, 0x01 }; 2468c2ecf20Sopenharmony_ci u8 m[53], t[16]; 2478c2ecf20Sopenharmony_ci int err; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci SMP_DBG("w %32phN", w); 2508c2ecf20Sopenharmony_ci SMP_DBG("n1 %16phN n2 %16phN", n1, n2); 2518c2ecf20Sopenharmony_ci SMP_DBG("a1 %7phN a2 %7phN", a1, a2); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, salt, w, 32, t); 2548c2ecf20Sopenharmony_ci if (err) 2558c2ecf20Sopenharmony_ci return err; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci SMP_DBG("t %16phN", t); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci memcpy(m, length, 2); 2608c2ecf20Sopenharmony_ci memcpy(m + 2, a2, 7); 2618c2ecf20Sopenharmony_ci memcpy(m + 9, a1, 7); 2628c2ecf20Sopenharmony_ci memcpy(m + 16, n2, 16); 2638c2ecf20Sopenharmony_ci memcpy(m + 32, n1, 16); 2648c2ecf20Sopenharmony_ci memcpy(m + 48, btle, 4); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci m[52] = 0; /* Counter */ 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey); 2698c2ecf20Sopenharmony_ci if (err) 2708c2ecf20Sopenharmony_ci return err; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci SMP_DBG("mackey %16phN", mackey); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci m[52] = 1; /* Counter */ 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk); 2778c2ecf20Sopenharmony_ci if (err) 2788c2ecf20Sopenharmony_ci return err; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci SMP_DBG("ltk %16phN", ltk); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic int smp_f6(struct crypto_shash *tfm_cmac, const u8 w[16], 2868c2ecf20Sopenharmony_ci const u8 n1[16], const u8 n2[16], const u8 r[16], 2878c2ecf20Sopenharmony_ci const u8 io_cap[3], const u8 a1[7], const u8 a2[7], 2888c2ecf20Sopenharmony_ci u8 res[16]) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci u8 m[65]; 2918c2ecf20Sopenharmony_ci int err; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci SMP_DBG("w %16phN", w); 2948c2ecf20Sopenharmony_ci SMP_DBG("n1 %16phN n2 %16phN", n1, n2); 2958c2ecf20Sopenharmony_ci SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci memcpy(m, a2, 7); 2988c2ecf20Sopenharmony_ci memcpy(m + 7, a1, 7); 2998c2ecf20Sopenharmony_ci memcpy(m + 14, io_cap, 3); 3008c2ecf20Sopenharmony_ci memcpy(m + 17, r, 16); 3018c2ecf20Sopenharmony_ci memcpy(m + 33, n2, 16); 3028c2ecf20Sopenharmony_ci memcpy(m + 49, n1, 16); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, w, m, sizeof(m), res); 3058c2ecf20Sopenharmony_ci if (err) 3068c2ecf20Sopenharmony_ci return err; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci SMP_DBG("res %16phN", res); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci return err; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic int smp_g2(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 v[32], 3148c2ecf20Sopenharmony_ci const u8 x[16], const u8 y[16], u32 *val) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci u8 m[80], tmp[16]; 3178c2ecf20Sopenharmony_ci int err; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci SMP_DBG("u %32phN", u); 3208c2ecf20Sopenharmony_ci SMP_DBG("v %32phN", v); 3218c2ecf20Sopenharmony_ci SMP_DBG("x %16phN y %16phN", x, y); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci memcpy(m, y, 16); 3248c2ecf20Sopenharmony_ci memcpy(m + 16, v, 32); 3258c2ecf20Sopenharmony_ci memcpy(m + 48, u, 32); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp); 3288c2ecf20Sopenharmony_ci if (err) 3298c2ecf20Sopenharmony_ci return err; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci *val = get_unaligned_le32(tmp); 3328c2ecf20Sopenharmony_ci *val %= 1000000; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci SMP_DBG("val %06u", *val); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci return 0; 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16], 3408c2ecf20Sopenharmony_ci const u8 key_id[4], u8 res[16]) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci int err; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci SMP_DBG("w %16phN key_id %4phN", w, key_id); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, w, key_id, 4, res); 3478c2ecf20Sopenharmony_ci if (err) 3488c2ecf20Sopenharmony_ci return err; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci SMP_DBG("res %16phN", res); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return err; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16], 3568c2ecf20Sopenharmony_ci const u8 salt[16], u8 res[16]) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci int err; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci SMP_DBG("w %16phN salt %16phN", w, salt); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci err = aes_cmac(tfm_cmac, salt, w, 16, res); 3638c2ecf20Sopenharmony_ci if (err) 3648c2ecf20Sopenharmony_ci return err; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci SMP_DBG("res %16phN", res); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci return err; 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/* The following functions map to the legacy SMP crypto functions e, c1, 3728c2ecf20Sopenharmony_ci * s1 and ah. 3738c2ecf20Sopenharmony_ci */ 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic int smp_e(const u8 *k, u8 *r) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci struct crypto_aes_ctx ctx; 3788c2ecf20Sopenharmony_ci uint8_t tmp[16], data[16]; 3798c2ecf20Sopenharmony_ci int err; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci SMP_DBG("k %16phN r %16phN", k, r); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* The most significant octet of key corresponds to k[0] */ 3848c2ecf20Sopenharmony_ci swap_buf(k, tmp, 16); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci err = aes_expandkey(&ctx, tmp, 16); 3878c2ecf20Sopenharmony_ci if (err) { 3888c2ecf20Sopenharmony_ci BT_ERR("cipher setkey failed: %d", err); 3898c2ecf20Sopenharmony_ci return err; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* Most significant octet of plaintextData corresponds to data[0] */ 3938c2ecf20Sopenharmony_ci swap_buf(r, data, 16); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci aes_encrypt(&ctx, data, data); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* Most significant octet of encryptedData corresponds to data[0] */ 3988c2ecf20Sopenharmony_ci swap_buf(data, r, 16); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci SMP_DBG("r %16phN", r); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci memzero_explicit(&ctx, sizeof (ctx)); 4038c2ecf20Sopenharmony_ci return err; 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic int smp_c1(const u8 k[16], 4078c2ecf20Sopenharmony_ci const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat, 4088c2ecf20Sopenharmony_ci const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16]) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci u8 p1[16], p2[16]; 4118c2ecf20Sopenharmony_ci int err; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci SMP_DBG("k %16phN r %16phN", k, r); 4148c2ecf20Sopenharmony_ci SMP_DBG("iat %u ia %6phN rat %u ra %6phN", _iat, ia, _rat, ra); 4158c2ecf20Sopenharmony_ci SMP_DBG("preq %7phN pres %7phN", preq, pres); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci memset(p1, 0, 16); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* p1 = pres || preq || _rat || _iat */ 4208c2ecf20Sopenharmony_ci p1[0] = _iat; 4218c2ecf20Sopenharmony_ci p1[1] = _rat; 4228c2ecf20Sopenharmony_ci memcpy(p1 + 2, preq, 7); 4238c2ecf20Sopenharmony_ci memcpy(p1 + 9, pres, 7); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci SMP_DBG("p1 %16phN", p1); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* res = r XOR p1 */ 4288c2ecf20Sopenharmony_ci u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* res = e(k, res) */ 4318c2ecf20Sopenharmony_ci err = smp_e(k, res); 4328c2ecf20Sopenharmony_ci if (err) { 4338c2ecf20Sopenharmony_ci BT_ERR("Encrypt data error"); 4348c2ecf20Sopenharmony_ci return err; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* p2 = padding || ia || ra */ 4388c2ecf20Sopenharmony_ci memcpy(p2, ra, 6); 4398c2ecf20Sopenharmony_ci memcpy(p2 + 6, ia, 6); 4408c2ecf20Sopenharmony_ci memset(p2 + 12, 0, 4); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci SMP_DBG("p2 %16phN", p2); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* res = res XOR p2 */ 4458c2ecf20Sopenharmony_ci u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci /* res = e(k, res) */ 4488c2ecf20Sopenharmony_ci err = smp_e(k, res); 4498c2ecf20Sopenharmony_ci if (err) 4508c2ecf20Sopenharmony_ci BT_ERR("Encrypt data error"); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return err; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic int smp_s1(const u8 k[16], 4568c2ecf20Sopenharmony_ci const u8 r1[16], const u8 r2[16], u8 _r[16]) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci int err; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* Just least significant octets from r1 and r2 are considered */ 4618c2ecf20Sopenharmony_ci memcpy(_r, r2, 8); 4628c2ecf20Sopenharmony_ci memcpy(_r + 8, r1, 8); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci err = smp_e(k, _r); 4658c2ecf20Sopenharmony_ci if (err) 4668c2ecf20Sopenharmony_ci BT_ERR("Encrypt data error"); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci return err; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic int smp_ah(const u8 irk[16], const u8 r[3], u8 res[3]) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci u8 _res[16]; 4748c2ecf20Sopenharmony_ci int err; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci /* r' = padding || r */ 4778c2ecf20Sopenharmony_ci memcpy(_res, r, 3); 4788c2ecf20Sopenharmony_ci memset(_res + 3, 0, 13); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci err = smp_e(irk, _res); 4818c2ecf20Sopenharmony_ci if (err) { 4828c2ecf20Sopenharmony_ci BT_ERR("Encrypt error"); 4838c2ecf20Sopenharmony_ci return err; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci /* The output of the random address function ah is: 4878c2ecf20Sopenharmony_ci * ah(k, r) = e(k, r') mod 2^24 4888c2ecf20Sopenharmony_ci * The output of the security function e is then truncated to 24 bits 4898c2ecf20Sopenharmony_ci * by taking the least significant 24 bits of the output of e as the 4908c2ecf20Sopenharmony_ci * result of ah. 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci memcpy(res, _res, 3); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cibool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], 4988c2ecf20Sopenharmony_ci const bdaddr_t *bdaddr) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci struct l2cap_chan *chan = hdev->smp_data; 5018c2ecf20Sopenharmony_ci u8 hash[3]; 5028c2ecf20Sopenharmony_ci int err; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci if (!chan || !chan->data) 5058c2ecf20Sopenharmony_ci return false; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "RPA %pMR IRK %*phN", bdaddr, 16, irk); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci err = smp_ah(irk, &bdaddr->b[3], hash); 5108c2ecf20Sopenharmony_ci if (err) 5118c2ecf20Sopenharmony_ci return false; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return !crypto_memneq(bdaddr->b, hash, 3); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ciint smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci struct l2cap_chan *chan = hdev->smp_data; 5198c2ecf20Sopenharmony_ci int err; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci if (!chan || !chan->data) 5228c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci get_random_bytes(&rpa->b[3], 3); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci rpa->b[5] &= 0x3f; /* Clear two most significant bits */ 5278c2ecf20Sopenharmony_ci rpa->b[5] |= 0x40; /* Set second most significant bit */ 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci err = smp_ah(irk, &rpa->b[3], rpa->b); 5308c2ecf20Sopenharmony_ci if (err < 0) 5318c2ecf20Sopenharmony_ci return err; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "RPA %pMR", rpa); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci return 0; 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ciint smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci struct l2cap_chan *chan = hdev->smp_data; 5418c2ecf20Sopenharmony_ci struct smp_dev *smp; 5428c2ecf20Sopenharmony_ci int err; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (!chan || !chan->data) 5458c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci smp = chan->data; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) { 5508c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Using debug keys"); 5518c2ecf20Sopenharmony_ci err = set_ecdh_privkey(smp->tfm_ecdh, debug_sk); 5528c2ecf20Sopenharmony_ci if (err) 5538c2ecf20Sopenharmony_ci return err; 5548c2ecf20Sopenharmony_ci memcpy(smp->local_pk, debug_pk, 64); 5558c2ecf20Sopenharmony_ci smp->debug_key = true; 5568c2ecf20Sopenharmony_ci } else { 5578c2ecf20Sopenharmony_ci while (true) { 5588c2ecf20Sopenharmony_ci /* Generate key pair for Secure Connections */ 5598c2ecf20Sopenharmony_ci err = generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk); 5608c2ecf20Sopenharmony_ci if (err) 5618c2ecf20Sopenharmony_ci return err; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci /* This is unlikely, but we need to check that 5648c2ecf20Sopenharmony_ci * we didn't accidentially generate a debug key. 5658c2ecf20Sopenharmony_ci */ 5668c2ecf20Sopenharmony_ci if (crypto_memneq(smp->local_pk, debug_pk, 64)) 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci smp->debug_key = false; 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci SMP_DBG("OOB Public Key X: %32phN", smp->local_pk); 5738c2ecf20Sopenharmony_ci SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci get_random_bytes(smp->local_rand, 16); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk, 5788c2ecf20Sopenharmony_ci smp->local_rand, 0, hash); 5798c2ecf20Sopenharmony_ci if (err < 0) 5808c2ecf20Sopenharmony_ci return err; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci memcpy(rand, smp->local_rand, 16); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci smp->local_oob = true; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci return 0; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 5928c2ecf20Sopenharmony_ci struct smp_chan *smp; 5938c2ecf20Sopenharmony_ci struct kvec iv[2]; 5948c2ecf20Sopenharmony_ci struct msghdr msg; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (!chan) 5978c2ecf20Sopenharmony_ci return; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "code 0x%2.2x", code); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci iv[0].iov_base = &code; 6028c2ecf20Sopenharmony_ci iv[0].iov_len = 1; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci iv[1].iov_base = data; 6058c2ecf20Sopenharmony_ci iv[1].iov_len = len; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci iov_iter_kvec(&msg.msg_iter, WRITE, iv, 2, 1 + len); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci l2cap_chan_send(chan, &msg, 1 + len); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (!chan->data) 6148c2ecf20Sopenharmony_ci return; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci smp = chan->data; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&smp->security_timer); 6198c2ecf20Sopenharmony_ci schedule_delayed_work(&smp->security_timer, SMP_TIMEOUT); 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic u8 authreq_to_seclevel(u8 authreq) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci if (authreq & SMP_AUTH_MITM) { 6258c2ecf20Sopenharmony_ci if (authreq & SMP_AUTH_SC) 6268c2ecf20Sopenharmony_ci return BT_SECURITY_FIPS; 6278c2ecf20Sopenharmony_ci else 6288c2ecf20Sopenharmony_ci return BT_SECURITY_HIGH; 6298c2ecf20Sopenharmony_ci } else { 6308c2ecf20Sopenharmony_ci return BT_SECURITY_MEDIUM; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic __u8 seclevel_to_authreq(__u8 sec_level) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci switch (sec_level) { 6378c2ecf20Sopenharmony_ci case BT_SECURITY_FIPS: 6388c2ecf20Sopenharmony_ci case BT_SECURITY_HIGH: 6398c2ecf20Sopenharmony_ci return SMP_AUTH_MITM | SMP_AUTH_BONDING; 6408c2ecf20Sopenharmony_ci case BT_SECURITY_MEDIUM: 6418c2ecf20Sopenharmony_ci return SMP_AUTH_BONDING; 6428c2ecf20Sopenharmony_ci default: 6438c2ecf20Sopenharmony_ci return SMP_AUTH_NONE; 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic void build_pairing_cmd(struct l2cap_conn *conn, 6488c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req, 6498c2ecf20Sopenharmony_ci struct smp_cmd_pairing *rsp, __u8 authreq) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 6528c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 6538c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 6548c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 6558c2ecf20Sopenharmony_ci u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_BONDABLE)) { 6588c2ecf20Sopenharmony_ci local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; 6598c2ecf20Sopenharmony_ci remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; 6608c2ecf20Sopenharmony_ci authreq |= SMP_AUTH_BONDING; 6618c2ecf20Sopenharmony_ci } else { 6628c2ecf20Sopenharmony_ci authreq &= ~SMP_AUTH_BONDING; 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING)) 6668c2ecf20Sopenharmony_ci remote_dist |= SMP_DIST_ID_KEY; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PRIVACY)) 6698c2ecf20Sopenharmony_ci local_dist |= SMP_DIST_ID_KEY; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) && 6728c2ecf20Sopenharmony_ci (authreq & SMP_AUTH_SC)) { 6738c2ecf20Sopenharmony_ci struct oob_data *oob_data; 6748c2ecf20Sopenharmony_ci u8 bdaddr_type; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) { 6778c2ecf20Sopenharmony_ci local_dist |= SMP_DIST_LINK_KEY; 6788c2ecf20Sopenharmony_ci remote_dist |= SMP_DIST_LINK_KEY; 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci if (hcon->dst_type == ADDR_LE_DEV_PUBLIC) 6828c2ecf20Sopenharmony_ci bdaddr_type = BDADDR_LE_PUBLIC; 6838c2ecf20Sopenharmony_ci else 6848c2ecf20Sopenharmony_ci bdaddr_type = BDADDR_LE_RANDOM; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci oob_data = hci_find_remote_oob_data(hdev, &hcon->dst, 6878c2ecf20Sopenharmony_ci bdaddr_type); 6888c2ecf20Sopenharmony_ci if (oob_data && oob_data->present) { 6898c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_REMOTE_OOB, &smp->flags); 6908c2ecf20Sopenharmony_ci oob_flag = SMP_OOB_PRESENT; 6918c2ecf20Sopenharmony_ci memcpy(smp->rr, oob_data->rand256, 16); 6928c2ecf20Sopenharmony_ci memcpy(smp->pcnf, oob_data->hash256, 16); 6938c2ecf20Sopenharmony_ci SMP_DBG("OOB Remote Confirmation: %16phN", smp->pcnf); 6948c2ecf20Sopenharmony_ci SMP_DBG("OOB Remote Random: %16phN", smp->rr); 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci } else { 6988c2ecf20Sopenharmony_ci authreq &= ~SMP_AUTH_SC; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci if (rsp == NULL) { 7028c2ecf20Sopenharmony_ci req->io_capability = conn->hcon->io_capability; 7038c2ecf20Sopenharmony_ci req->oob_flag = oob_flag; 7048c2ecf20Sopenharmony_ci req->max_key_size = hdev->le_max_key_size; 7058c2ecf20Sopenharmony_ci req->init_key_dist = local_dist; 7068c2ecf20Sopenharmony_ci req->resp_key_dist = remote_dist; 7078c2ecf20Sopenharmony_ci req->auth_req = (authreq & AUTH_REQ_MASK(hdev)); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci smp->remote_key_dist = remote_dist; 7108c2ecf20Sopenharmony_ci return; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci rsp->io_capability = conn->hcon->io_capability; 7148c2ecf20Sopenharmony_ci rsp->oob_flag = oob_flag; 7158c2ecf20Sopenharmony_ci rsp->max_key_size = hdev->le_max_key_size; 7168c2ecf20Sopenharmony_ci rsp->init_key_dist = req->init_key_dist & remote_dist; 7178c2ecf20Sopenharmony_ci rsp->resp_key_dist = req->resp_key_dist & local_dist; 7188c2ecf20Sopenharmony_ci rsp->auth_req = (authreq & AUTH_REQ_MASK(hdev)); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci smp->remote_key_dist = rsp->init_key_dist; 7218c2ecf20Sopenharmony_ci} 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_cistatic u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 7248c2ecf20Sopenharmony_ci{ 7258c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 7268c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hcon->hdev; 7278c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci if (conn->hcon->pending_sec_level == BT_SECURITY_FIPS && 7308c2ecf20Sopenharmony_ci max_key_size != SMP_MAX_ENC_KEY_SIZE) 7318c2ecf20Sopenharmony_ci return SMP_ENC_KEY_SIZE; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci if (max_key_size > hdev->le_max_key_size || 7348c2ecf20Sopenharmony_ci max_key_size < SMP_MIN_ENC_KEY_SIZE) 7358c2ecf20Sopenharmony_ci return SMP_ENC_KEY_SIZE; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci smp->enc_key_size = max_key_size; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci return 0; 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic void smp_chan_destroy(struct l2cap_conn *conn) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 7458c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 7468c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 7478c2ecf20Sopenharmony_ci bool complete; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci BUG_ON(!smp); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&smp->security_timer); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags); 7548c2ecf20Sopenharmony_ci mgmt_smp_complete(hcon, complete); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci kfree_sensitive(smp->csrk); 7578c2ecf20Sopenharmony_ci kfree_sensitive(smp->responder_csrk); 7588c2ecf20Sopenharmony_ci kfree_sensitive(smp->link_key); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci crypto_free_shash(smp->tfm_cmac); 7618c2ecf20Sopenharmony_ci crypto_free_kpp(smp->tfm_ecdh); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Ensure that we don't leave any debug key around if debug key 7648c2ecf20Sopenharmony_ci * support hasn't been explicitly enabled. 7658c2ecf20Sopenharmony_ci */ 7668c2ecf20Sopenharmony_ci if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG && 7678c2ecf20Sopenharmony_ci !hci_dev_test_flag(hcon->hdev, HCI_KEEP_DEBUG_KEYS)) { 7688c2ecf20Sopenharmony_ci list_del_rcu(&smp->ltk->list); 7698c2ecf20Sopenharmony_ci kfree_rcu(smp->ltk, rcu); 7708c2ecf20Sopenharmony_ci smp->ltk = NULL; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci /* If pairing failed clean up any keys we might have */ 7748c2ecf20Sopenharmony_ci if (!complete) { 7758c2ecf20Sopenharmony_ci if (smp->ltk) { 7768c2ecf20Sopenharmony_ci list_del_rcu(&smp->ltk->list); 7778c2ecf20Sopenharmony_ci kfree_rcu(smp->ltk, rcu); 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci if (smp->responder_ltk) { 7818c2ecf20Sopenharmony_ci list_del_rcu(&smp->responder_ltk->list); 7828c2ecf20Sopenharmony_ci kfree_rcu(smp->responder_ltk, rcu); 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci if (smp->remote_irk) { 7868c2ecf20Sopenharmony_ci list_del_rcu(&smp->remote_irk->list); 7878c2ecf20Sopenharmony_ci kfree_rcu(smp->remote_irk, rcu); 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci chan->data = NULL; 7928c2ecf20Sopenharmony_ci kfree_sensitive(smp); 7938c2ecf20Sopenharmony_ci hci_conn_drop(hcon); 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cistatic void smp_failure(struct l2cap_conn *conn, u8 reason) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 7998c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (reason) 8028c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), 8038c2ecf20Sopenharmony_ci &reason); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci mgmt_auth_failed(hcon, HCI_ERROR_AUTH_FAILURE); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (chan->data) 8088c2ecf20Sopenharmony_ci smp_chan_destroy(conn); 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci#define JUST_WORKS 0x00 8128c2ecf20Sopenharmony_ci#define JUST_CFM 0x01 8138c2ecf20Sopenharmony_ci#define REQ_PASSKEY 0x02 8148c2ecf20Sopenharmony_ci#define CFM_PASSKEY 0x03 8158c2ecf20Sopenharmony_ci#define REQ_OOB 0x04 8168c2ecf20Sopenharmony_ci#define DSP_PASSKEY 0x05 8178c2ecf20Sopenharmony_ci#define OVERLAP 0xFF 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic const u8 gen_method[5][5] = { 8208c2ecf20Sopenharmony_ci { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 8218c2ecf20Sopenharmony_ci { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 8228c2ecf20Sopenharmony_ci { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 8238c2ecf20Sopenharmony_ci { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 8248c2ecf20Sopenharmony_ci { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, 8258c2ecf20Sopenharmony_ci}; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_cistatic const u8 sc_method[5][5] = { 8288c2ecf20Sopenharmony_ci { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, 8298c2ecf20Sopenharmony_ci { JUST_WORKS, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 8308c2ecf20Sopenharmony_ci { DSP_PASSKEY, DSP_PASSKEY, REQ_PASSKEY, JUST_WORKS, DSP_PASSKEY }, 8318c2ecf20Sopenharmony_ci { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, 8328c2ecf20Sopenharmony_ci { DSP_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, 8338c2ecf20Sopenharmony_ci}; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_cistatic u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci /* If either side has unknown io_caps, use JUST_CFM (which gets 8388c2ecf20Sopenharmony_ci * converted later to JUST_WORKS if we're initiators. 8398c2ecf20Sopenharmony_ci */ 8408c2ecf20Sopenharmony_ci if (local_io > SMP_IO_KEYBOARD_DISPLAY || 8418c2ecf20Sopenharmony_ci remote_io > SMP_IO_KEYBOARD_DISPLAY) 8428c2ecf20Sopenharmony_ci return JUST_CFM; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) 8458c2ecf20Sopenharmony_ci return sc_method[remote_io][local_io]; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci return gen_method[remote_io][local_io]; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, 8518c2ecf20Sopenharmony_ci u8 local_io, u8 remote_io) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 8548c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 8558c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 8568c2ecf20Sopenharmony_ci u32 passkey = 0; 8578c2ecf20Sopenharmony_ci int ret; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* Initialize key for JUST WORKS */ 8608c2ecf20Sopenharmony_ci memset(smp->tk, 0, sizeof(smp->tk)); 8618c2ecf20Sopenharmony_ci clear_bit(SMP_FLAG_TK_VALID, &smp->flags); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "auth:%d lcl:%d rem:%d", auth, local_io, 8648c2ecf20Sopenharmony_ci remote_io); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* If neither side wants MITM, either "just" confirm an incoming 8678c2ecf20Sopenharmony_ci * request or use just-works for outgoing ones. The JUST_CFM 8688c2ecf20Sopenharmony_ci * will be converted to JUST_WORKS if necessary later in this 8698c2ecf20Sopenharmony_ci * function. If either side has MITM look up the method from the 8708c2ecf20Sopenharmony_ci * table. 8718c2ecf20Sopenharmony_ci */ 8728c2ecf20Sopenharmony_ci if (!(auth & SMP_AUTH_MITM)) 8738c2ecf20Sopenharmony_ci smp->method = JUST_CFM; 8748c2ecf20Sopenharmony_ci else 8758c2ecf20Sopenharmony_ci smp->method = get_auth_method(smp, local_io, remote_io); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* Don't confirm locally initiated pairing attempts */ 8788c2ecf20Sopenharmony_ci if (smp->method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, 8798c2ecf20Sopenharmony_ci &smp->flags)) 8808c2ecf20Sopenharmony_ci smp->method = JUST_WORKS; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci /* Don't bother user space with no IO capabilities */ 8838c2ecf20Sopenharmony_ci if (smp->method == JUST_CFM && 8848c2ecf20Sopenharmony_ci hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) 8858c2ecf20Sopenharmony_ci smp->method = JUST_WORKS; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* If Just Works, Continue with Zero TK and ask user-space for 8888c2ecf20Sopenharmony_ci * confirmation */ 8898c2ecf20Sopenharmony_ci if (smp->method == JUST_WORKS) { 8908c2ecf20Sopenharmony_ci ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, 8918c2ecf20Sopenharmony_ci hcon->type, 8928c2ecf20Sopenharmony_ci hcon->dst_type, 8938c2ecf20Sopenharmony_ci passkey, 1); 8948c2ecf20Sopenharmony_ci if (ret) 8958c2ecf20Sopenharmony_ci return ret; 8968c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_WAIT_USER, &smp->flags); 8978c2ecf20Sopenharmony_ci return 0; 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* If this function is used for SC -> legacy fallback we 9018c2ecf20Sopenharmony_ci * can only recover the just-works case. 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) 9048c2ecf20Sopenharmony_ci return -EINVAL; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci /* Not Just Works/Confirm results in MITM Authentication */ 9078c2ecf20Sopenharmony_ci if (smp->method != JUST_CFM) { 9088c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_MITM_AUTH, &smp->flags); 9098c2ecf20Sopenharmony_ci if (hcon->pending_sec_level < BT_SECURITY_HIGH) 9108c2ecf20Sopenharmony_ci hcon->pending_sec_level = BT_SECURITY_HIGH; 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci /* If both devices have Keyboard-Display I/O, the initiator 9148c2ecf20Sopenharmony_ci * Confirms and the responder Enters the passkey. 9158c2ecf20Sopenharmony_ci */ 9168c2ecf20Sopenharmony_ci if (smp->method == OVERLAP) { 9178c2ecf20Sopenharmony_ci if (hcon->role == HCI_ROLE_MASTER) 9188c2ecf20Sopenharmony_ci smp->method = CFM_PASSKEY; 9198c2ecf20Sopenharmony_ci else 9208c2ecf20Sopenharmony_ci smp->method = REQ_PASSKEY; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* Generate random passkey. */ 9248c2ecf20Sopenharmony_ci if (smp->method == CFM_PASSKEY) { 9258c2ecf20Sopenharmony_ci memset(smp->tk, 0, sizeof(smp->tk)); 9268c2ecf20Sopenharmony_ci get_random_bytes(&passkey, sizeof(passkey)); 9278c2ecf20Sopenharmony_ci passkey %= 1000000; 9288c2ecf20Sopenharmony_ci put_unaligned_le32(passkey, smp->tk); 9298c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "PassKey: %d", passkey); 9308c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_TK_VALID, &smp->flags); 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY) 9348c2ecf20Sopenharmony_ci ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, 9358c2ecf20Sopenharmony_ci hcon->type, hcon->dst_type); 9368c2ecf20Sopenharmony_ci else if (smp->method == JUST_CFM) 9378c2ecf20Sopenharmony_ci ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, 9388c2ecf20Sopenharmony_ci hcon->type, hcon->dst_type, 9398c2ecf20Sopenharmony_ci passkey, 1); 9408c2ecf20Sopenharmony_ci else 9418c2ecf20Sopenharmony_ci ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst, 9428c2ecf20Sopenharmony_ci hcon->type, hcon->dst_type, 9438c2ecf20Sopenharmony_ci passkey, 0); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci return ret; 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic u8 smp_confirm(struct smp_chan *smp) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 9518c2ecf20Sopenharmony_ci struct smp_cmd_pairing_confirm cp; 9528c2ecf20Sopenharmony_ci int ret; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "conn %p", conn); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci ret = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp, 9578c2ecf20Sopenharmony_ci conn->hcon->init_addr_type, &conn->hcon->init_addr, 9588c2ecf20Sopenharmony_ci conn->hcon->resp_addr_type, &conn->hcon->resp_addr, 9598c2ecf20Sopenharmony_ci cp.confirm_val); 9608c2ecf20Sopenharmony_ci if (ret) 9618c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci if (conn->hcon->out) 9688c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 9698c2ecf20Sopenharmony_ci else 9708c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci return 0; 9738c2ecf20Sopenharmony_ci} 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_cistatic u8 smp_random(struct smp_chan *smp) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 9788c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 9798c2ecf20Sopenharmony_ci u8 confirm[16]; 9808c2ecf20Sopenharmony_ci int ret; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn, 9838c2ecf20Sopenharmony_ci conn->hcon->out ? "initiator" : "responder"); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, 9868c2ecf20Sopenharmony_ci hcon->init_addr_type, &hcon->init_addr, 9878c2ecf20Sopenharmony_ci hcon->resp_addr_type, &hcon->resp_addr, confirm); 9888c2ecf20Sopenharmony_ci if (ret) 9898c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { 9928c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "pairing failed " 9938c2ecf20Sopenharmony_ci "(confirmation values mismatch)"); 9948c2ecf20Sopenharmony_ci return SMP_CONFIRM_FAILED; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (hcon->out) { 9988c2ecf20Sopenharmony_ci u8 stk[16]; 9998c2ecf20Sopenharmony_ci __le64 rand = 0; 10008c2ecf20Sopenharmony_ci __le16 ediv = 0; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci smp_s1(smp->tk, smp->rrnd, smp->prnd, stk); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 10058c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci hci_le_start_enc(hcon, ediv, rand, stk, smp->enc_key_size); 10088c2ecf20Sopenharmony_ci hcon->enc_key_size = smp->enc_key_size; 10098c2ecf20Sopenharmony_ci set_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags); 10108c2ecf20Sopenharmony_ci } else { 10118c2ecf20Sopenharmony_ci u8 stk[16], auth; 10128c2ecf20Sopenharmony_ci __le64 rand = 0; 10138c2ecf20Sopenharmony_ci __le16 ediv = 0; 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), 10168c2ecf20Sopenharmony_ci smp->prnd); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci smp_s1(smp->tk, smp->prnd, smp->rrnd, stk); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci if (hcon->pending_sec_level == BT_SECURITY_HIGH) 10218c2ecf20Sopenharmony_ci auth = 1; 10228c2ecf20Sopenharmony_ci else 10238c2ecf20Sopenharmony_ci auth = 0; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* Even though there's no _RESPONDER suffix this is the 10268c2ecf20Sopenharmony_ci * responder STK we're adding for later lookup (the initiator 10278c2ecf20Sopenharmony_ci * STK never needs to be stored). 10288c2ecf20Sopenharmony_ci */ 10298c2ecf20Sopenharmony_ci hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, 10308c2ecf20Sopenharmony_ci SMP_STK, auth, stk, smp->enc_key_size, ediv, rand); 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci return 0; 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_cistatic void smp_notify_keys(struct l2cap_conn *conn) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 10398c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 10408c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 10418c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 10428c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req = (void *) &smp->preq[1]; 10438c2ecf20Sopenharmony_ci struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1]; 10448c2ecf20Sopenharmony_ci bool persistent; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if (hcon->type == ACL_LINK) { 10478c2ecf20Sopenharmony_ci if (hcon->key_type == HCI_LK_DEBUG_COMBINATION) 10488c2ecf20Sopenharmony_ci persistent = false; 10498c2ecf20Sopenharmony_ci else 10508c2ecf20Sopenharmony_ci persistent = !test_bit(HCI_CONN_FLUSH_KEY, 10518c2ecf20Sopenharmony_ci &hcon->flags); 10528c2ecf20Sopenharmony_ci } else { 10538c2ecf20Sopenharmony_ci /* The LTKs, IRKs and CSRKs should be persistent only if 10548c2ecf20Sopenharmony_ci * both sides had the bonding bit set in their 10558c2ecf20Sopenharmony_ci * authentication requests. 10568c2ecf20Sopenharmony_ci */ 10578c2ecf20Sopenharmony_ci persistent = !!((req->auth_req & rsp->auth_req) & 10588c2ecf20Sopenharmony_ci SMP_AUTH_BONDING); 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (smp->remote_irk) { 10628c2ecf20Sopenharmony_ci smp->remote_irk->link_type = hcon->type; 10638c2ecf20Sopenharmony_ci mgmt_new_irk(hdev, smp->remote_irk, persistent); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci /* Now that user space can be considered to know the 10668c2ecf20Sopenharmony_ci * identity address track the connection based on it 10678c2ecf20Sopenharmony_ci * from now on (assuming this is an LE link). 10688c2ecf20Sopenharmony_ci */ 10698c2ecf20Sopenharmony_ci if (hcon->type == LE_LINK) { 10708c2ecf20Sopenharmony_ci bacpy(&hcon->dst, &smp->remote_irk->bdaddr); 10718c2ecf20Sopenharmony_ci hcon->dst_type = smp->remote_irk->addr_type; 10728c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &conn->id_addr_update_work); 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci if (smp->csrk) { 10778c2ecf20Sopenharmony_ci smp->csrk->link_type = hcon->type; 10788c2ecf20Sopenharmony_ci smp->csrk->bdaddr_type = hcon->dst_type; 10798c2ecf20Sopenharmony_ci bacpy(&smp->csrk->bdaddr, &hcon->dst); 10808c2ecf20Sopenharmony_ci mgmt_new_csrk(hdev, smp->csrk, persistent); 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (smp->responder_csrk) { 10848c2ecf20Sopenharmony_ci smp->responder_csrk->link_type = hcon->type; 10858c2ecf20Sopenharmony_ci smp->responder_csrk->bdaddr_type = hcon->dst_type; 10868c2ecf20Sopenharmony_ci bacpy(&smp->responder_csrk->bdaddr, &hcon->dst); 10878c2ecf20Sopenharmony_ci mgmt_new_csrk(hdev, smp->responder_csrk, persistent); 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (smp->ltk) { 10918c2ecf20Sopenharmony_ci smp->ltk->link_type = hcon->type; 10928c2ecf20Sopenharmony_ci smp->ltk->bdaddr_type = hcon->dst_type; 10938c2ecf20Sopenharmony_ci bacpy(&smp->ltk->bdaddr, &hcon->dst); 10948c2ecf20Sopenharmony_ci mgmt_new_ltk(hdev, smp->ltk, persistent); 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci if (smp->responder_ltk) { 10988c2ecf20Sopenharmony_ci smp->responder_ltk->link_type = hcon->type; 10998c2ecf20Sopenharmony_ci smp->responder_ltk->bdaddr_type = hcon->dst_type; 11008c2ecf20Sopenharmony_ci bacpy(&smp->responder_ltk->bdaddr, &hcon->dst); 11018c2ecf20Sopenharmony_ci mgmt_new_ltk(hdev, smp->responder_ltk, persistent); 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (smp->link_key) { 11058c2ecf20Sopenharmony_ci struct link_key *key; 11068c2ecf20Sopenharmony_ci u8 type; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags)) 11098c2ecf20Sopenharmony_ci type = HCI_LK_DEBUG_COMBINATION; 11108c2ecf20Sopenharmony_ci else if (hcon->sec_level == BT_SECURITY_FIPS) 11118c2ecf20Sopenharmony_ci type = HCI_LK_AUTH_COMBINATION_P256; 11128c2ecf20Sopenharmony_ci else 11138c2ecf20Sopenharmony_ci type = HCI_LK_UNAUTH_COMBINATION_P256; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci key = hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst, 11168c2ecf20Sopenharmony_ci smp->link_key, type, 0, &persistent); 11178c2ecf20Sopenharmony_ci if (key) { 11188c2ecf20Sopenharmony_ci key->link_type = hcon->type; 11198c2ecf20Sopenharmony_ci key->bdaddr_type = hcon->dst_type; 11208c2ecf20Sopenharmony_ci mgmt_new_link_key(hdev, key, persistent); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* Don't keep debug keys around if the relevant 11238c2ecf20Sopenharmony_ci * flag is not set. 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS) && 11268c2ecf20Sopenharmony_ci key->type == HCI_LK_DEBUG_COMBINATION) { 11278c2ecf20Sopenharmony_ci list_del_rcu(&key->list); 11288c2ecf20Sopenharmony_ci kfree_rcu(key, rcu); 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci} 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_cistatic void sc_add_ltk(struct smp_chan *smp) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct hci_conn *hcon = smp->conn->hcon; 11378c2ecf20Sopenharmony_ci u8 key_type, auth; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags)) 11408c2ecf20Sopenharmony_ci key_type = SMP_LTK_P256_DEBUG; 11418c2ecf20Sopenharmony_ci else 11428c2ecf20Sopenharmony_ci key_type = SMP_LTK_P256; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci if (hcon->pending_sec_level == BT_SECURITY_FIPS) 11458c2ecf20Sopenharmony_ci auth = 1; 11468c2ecf20Sopenharmony_ci else 11478c2ecf20Sopenharmony_ci auth = 0; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, 11508c2ecf20Sopenharmony_ci key_type, auth, smp->tk, smp->enc_key_size, 11518c2ecf20Sopenharmony_ci 0, 0); 11528c2ecf20Sopenharmony_ci} 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_cistatic void sc_generate_link_key(struct smp_chan *smp) 11558c2ecf20Sopenharmony_ci{ 11568c2ecf20Sopenharmony_ci /* From core spec. Spells out in ASCII as 'lebr'. */ 11578c2ecf20Sopenharmony_ci const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c }; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci smp->link_key = kzalloc(16, GFP_KERNEL); 11608c2ecf20Sopenharmony_ci if (!smp->link_key) 11618c2ecf20Sopenharmony_ci return; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_CT2, &smp->flags)) { 11648c2ecf20Sopenharmony_ci /* SALT = 0x000000000000000000000000746D7031 */ 11658c2ecf20Sopenharmony_ci const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 }; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) { 11688c2ecf20Sopenharmony_ci kfree_sensitive(smp->link_key); 11698c2ecf20Sopenharmony_ci smp->link_key = NULL; 11708c2ecf20Sopenharmony_ci return; 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci } else { 11738c2ecf20Sopenharmony_ci /* From core spec. Spells out in ASCII as 'tmp1'. */ 11748c2ecf20Sopenharmony_ci const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 }; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) { 11778c2ecf20Sopenharmony_ci kfree_sensitive(smp->link_key); 11788c2ecf20Sopenharmony_ci smp->link_key = NULL; 11798c2ecf20Sopenharmony_ci return; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) { 11848c2ecf20Sopenharmony_ci kfree_sensitive(smp->link_key); 11858c2ecf20Sopenharmony_ci smp->link_key = NULL; 11868c2ecf20Sopenharmony_ci return; 11878c2ecf20Sopenharmony_ci } 11888c2ecf20Sopenharmony_ci} 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_cistatic void smp_allow_key_dist(struct smp_chan *smp) 11918c2ecf20Sopenharmony_ci{ 11928c2ecf20Sopenharmony_ci /* Allow the first expected phase 3 PDU. The rest of the PDUs 11938c2ecf20Sopenharmony_ci * will be allowed in each PDU handler to ensure we receive 11948c2ecf20Sopenharmony_ci * them in the correct order. 11958c2ecf20Sopenharmony_ci */ 11968c2ecf20Sopenharmony_ci if (smp->remote_key_dist & SMP_DIST_ENC_KEY) 11978c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_ENCRYPT_INFO); 11988c2ecf20Sopenharmony_ci else if (smp->remote_key_dist & SMP_DIST_ID_KEY) 11998c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_IDENT_INFO); 12008c2ecf20Sopenharmony_ci else if (smp->remote_key_dist & SMP_DIST_SIGN) 12018c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO); 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic void sc_generate_ltk(struct smp_chan *smp) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci /* From core spec. Spells out in ASCII as 'brle'. */ 12078c2ecf20Sopenharmony_ci const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 }; 12088c2ecf20Sopenharmony_ci struct hci_conn *hcon = smp->conn->hcon; 12098c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 12108c2ecf20Sopenharmony_ci struct link_key *key; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci key = hci_find_link_key(hdev, &hcon->dst); 12138c2ecf20Sopenharmony_ci if (!key) { 12148c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no Link Key found to generate LTK"); 12158c2ecf20Sopenharmony_ci return; 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci if (key->type == HCI_LK_DEBUG_COMBINATION) 12198c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_CT2, &smp->flags)) { 12228c2ecf20Sopenharmony_ci /* SALT = 0x000000000000000000000000746D7032 */ 12238c2ecf20Sopenharmony_ci const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 }; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk)) 12268c2ecf20Sopenharmony_ci return; 12278c2ecf20Sopenharmony_ci } else { 12288c2ecf20Sopenharmony_ci /* From core spec. Spells out in ASCII as 'tmp2'. */ 12298c2ecf20Sopenharmony_ci const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 }; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk)) 12328c2ecf20Sopenharmony_ci return; 12338c2ecf20Sopenharmony_ci } 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk)) 12368c2ecf20Sopenharmony_ci return; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci sc_add_ltk(smp); 12398c2ecf20Sopenharmony_ci} 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic void smp_distribute_keys(struct smp_chan *smp) 12428c2ecf20Sopenharmony_ci{ 12438c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req, *rsp; 12448c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 12458c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 12468c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 12478c2ecf20Sopenharmony_ci __u8 *keydist; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci rsp = (void *) &smp->prsp[1]; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* The responder sends its keys first */ 12548c2ecf20Sopenharmony_ci if (hcon->out && (smp->remote_key_dist & KEY_DIST_MASK)) { 12558c2ecf20Sopenharmony_ci smp_allow_key_dist(smp); 12568c2ecf20Sopenharmony_ci return; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci req = (void *) &smp->preq[1]; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci if (hcon->out) { 12628c2ecf20Sopenharmony_ci keydist = &rsp->init_key_dist; 12638c2ecf20Sopenharmony_ci *keydist &= req->init_key_dist; 12648c2ecf20Sopenharmony_ci } else { 12658c2ecf20Sopenharmony_ci keydist = &rsp->resp_key_dist; 12668c2ecf20Sopenharmony_ci *keydist &= req->resp_key_dist; 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) { 12708c2ecf20Sopenharmony_ci if (hcon->type == LE_LINK && (*keydist & SMP_DIST_LINK_KEY)) 12718c2ecf20Sopenharmony_ci sc_generate_link_key(smp); 12728c2ecf20Sopenharmony_ci if (hcon->type == ACL_LINK && (*keydist & SMP_DIST_ENC_KEY)) 12738c2ecf20Sopenharmony_ci sc_generate_ltk(smp); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci /* Clear the keys which are generated but not distributed */ 12768c2ecf20Sopenharmony_ci *keydist &= ~SMP_SC_NO_DIST; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "keydist 0x%x", *keydist); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci if (*keydist & SMP_DIST_ENC_KEY) { 12828c2ecf20Sopenharmony_ci struct smp_cmd_encrypt_info enc; 12838c2ecf20Sopenharmony_ci struct smp_cmd_initiator_ident ident; 12848c2ecf20Sopenharmony_ci struct smp_ltk *ltk; 12858c2ecf20Sopenharmony_ci u8 authenticated; 12868c2ecf20Sopenharmony_ci __le16 ediv; 12878c2ecf20Sopenharmony_ci __le64 rand; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* Make sure we generate only the significant amount of 12908c2ecf20Sopenharmony_ci * bytes based on the encryption key size, and set the rest 12918c2ecf20Sopenharmony_ci * of the value to zeroes. 12928c2ecf20Sopenharmony_ci */ 12938c2ecf20Sopenharmony_ci get_random_bytes(enc.ltk, smp->enc_key_size); 12948c2ecf20Sopenharmony_ci memset(enc.ltk + smp->enc_key_size, 0, 12958c2ecf20Sopenharmony_ci sizeof(enc.ltk) - smp->enc_key_size); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci get_random_bytes(&ediv, sizeof(ediv)); 12988c2ecf20Sopenharmony_ci get_random_bytes(&rand, sizeof(rand)); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci authenticated = hcon->sec_level == BT_SECURITY_HIGH; 13038c2ecf20Sopenharmony_ci ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, 13048c2ecf20Sopenharmony_ci SMP_LTK_RESPONDER, authenticated, enc.ltk, 13058c2ecf20Sopenharmony_ci smp->enc_key_size, ediv, rand); 13068c2ecf20Sopenharmony_ci smp->responder_ltk = ltk; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci ident.ediv = ediv; 13098c2ecf20Sopenharmony_ci ident.rand = rand; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_INITIATOR_IDENT, sizeof(ident), 13128c2ecf20Sopenharmony_ci &ident); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci *keydist &= ~SMP_DIST_ENC_KEY; 13158c2ecf20Sopenharmony_ci } 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci if (*keydist & SMP_DIST_ID_KEY) { 13188c2ecf20Sopenharmony_ci struct smp_cmd_ident_addr_info addrinfo; 13198c2ecf20Sopenharmony_ci struct smp_cmd_ident_info idinfo; 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci memcpy(idinfo.irk, hdev->irk, sizeof(idinfo.irk)); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* The hci_conn contains the local identity address 13268c2ecf20Sopenharmony_ci * after the connection has been established. 13278c2ecf20Sopenharmony_ci * 13288c2ecf20Sopenharmony_ci * This is true even when the connection has been 13298c2ecf20Sopenharmony_ci * established using a resolvable random address. 13308c2ecf20Sopenharmony_ci */ 13318c2ecf20Sopenharmony_ci bacpy(&addrinfo.bdaddr, &hcon->src); 13328c2ecf20Sopenharmony_ci addrinfo.addr_type = hcon->src_type; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), 13358c2ecf20Sopenharmony_ci &addrinfo); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci *keydist &= ~SMP_DIST_ID_KEY; 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci if (*keydist & SMP_DIST_SIGN) { 13418c2ecf20Sopenharmony_ci struct smp_cmd_sign_info sign; 13428c2ecf20Sopenharmony_ci struct smp_csrk *csrk; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci /* Generate a new random key */ 13458c2ecf20Sopenharmony_ci get_random_bytes(sign.csrk, sizeof(sign.csrk)); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); 13488c2ecf20Sopenharmony_ci if (csrk) { 13498c2ecf20Sopenharmony_ci if (hcon->sec_level > BT_SECURITY_MEDIUM) 13508c2ecf20Sopenharmony_ci csrk->type = MGMT_CSRK_LOCAL_AUTHENTICATED; 13518c2ecf20Sopenharmony_ci else 13528c2ecf20Sopenharmony_ci csrk->type = MGMT_CSRK_LOCAL_UNAUTHENTICATED; 13538c2ecf20Sopenharmony_ci memcpy(csrk->val, sign.csrk, sizeof(csrk->val)); 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci smp->responder_csrk = csrk; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci *keydist &= ~SMP_DIST_SIGN; 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci /* If there are still keys to be received wait for them */ 13638c2ecf20Sopenharmony_ci if (smp->remote_key_dist & KEY_DIST_MASK) { 13648c2ecf20Sopenharmony_ci smp_allow_key_dist(smp); 13658c2ecf20Sopenharmony_ci return; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_COMPLETE, &smp->flags); 13698c2ecf20Sopenharmony_ci smp_notify_keys(conn); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci smp_chan_destroy(conn); 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic void smp_timeout(struct work_struct *work) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci struct smp_chan *smp = container_of(work, struct smp_chan, 13778c2ecf20Sopenharmony_ci security_timer.work); 13788c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "conn %p", conn); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci hci_disconnect(conn->hcon, HCI_ERROR_REMOTE_USER_TERM); 13838c2ecf20Sopenharmony_ci} 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_cistatic struct smp_chan *smp_chan_create(struct l2cap_conn *conn) 13868c2ecf20Sopenharmony_ci{ 13878c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 13888c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 13898c2ecf20Sopenharmony_ci struct smp_chan *smp; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci smp = kzalloc(sizeof(*smp), GFP_ATOMIC); 13928c2ecf20Sopenharmony_ci if (!smp) 13938c2ecf20Sopenharmony_ci return NULL; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); 13968c2ecf20Sopenharmony_ci if (IS_ERR(smp->tfm_cmac)) { 13978c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "Unable to create CMAC crypto context"); 13988c2ecf20Sopenharmony_ci goto zfree_smp; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci smp->tfm_ecdh = crypto_alloc_kpp("ecdh", 0, 0); 14028c2ecf20Sopenharmony_ci if (IS_ERR(smp->tfm_ecdh)) { 14038c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "Unable to create ECDH crypto context"); 14048c2ecf20Sopenharmony_ci goto free_shash; 14058c2ecf20Sopenharmony_ci } 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci smp->conn = conn; 14088c2ecf20Sopenharmony_ci chan->data = smp; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_FAIL); 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&smp->security_timer, smp_timeout); 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci hci_conn_hold(hcon); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci return smp; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cifree_shash: 14198c2ecf20Sopenharmony_ci crypto_free_shash(smp->tfm_cmac); 14208c2ecf20Sopenharmony_cizfree_smp: 14218c2ecf20Sopenharmony_ci kfree_sensitive(smp); 14228c2ecf20Sopenharmony_ci return NULL; 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_cistatic int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16]) 14268c2ecf20Sopenharmony_ci{ 14278c2ecf20Sopenharmony_ci struct hci_conn *hcon = smp->conn->hcon; 14288c2ecf20Sopenharmony_ci u8 *na, *nb, a[7], b[7]; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci if (hcon->out) { 14318c2ecf20Sopenharmony_ci na = smp->prnd; 14328c2ecf20Sopenharmony_ci nb = smp->rrnd; 14338c2ecf20Sopenharmony_ci } else { 14348c2ecf20Sopenharmony_ci na = smp->rrnd; 14358c2ecf20Sopenharmony_ci nb = smp->prnd; 14368c2ecf20Sopenharmony_ci } 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci memcpy(a, &hcon->init_addr, 6); 14398c2ecf20Sopenharmony_ci memcpy(b, &hcon->resp_addr, 6); 14408c2ecf20Sopenharmony_ci a[6] = hcon->init_addr_type; 14418c2ecf20Sopenharmony_ci b[6] = hcon->resp_addr_type; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk); 14448c2ecf20Sopenharmony_ci} 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_cistatic void sc_dhkey_check(struct smp_chan *smp) 14478c2ecf20Sopenharmony_ci{ 14488c2ecf20Sopenharmony_ci struct hci_conn *hcon = smp->conn->hcon; 14498c2ecf20Sopenharmony_ci struct smp_cmd_dhkey_check check; 14508c2ecf20Sopenharmony_ci u8 a[7], b[7], *local_addr, *remote_addr; 14518c2ecf20Sopenharmony_ci u8 io_cap[3], r[16]; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci memcpy(a, &hcon->init_addr, 6); 14548c2ecf20Sopenharmony_ci memcpy(b, &hcon->resp_addr, 6); 14558c2ecf20Sopenharmony_ci a[6] = hcon->init_addr_type; 14568c2ecf20Sopenharmony_ci b[6] = hcon->resp_addr_type; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci if (hcon->out) { 14598c2ecf20Sopenharmony_ci local_addr = a; 14608c2ecf20Sopenharmony_ci remote_addr = b; 14618c2ecf20Sopenharmony_ci memcpy(io_cap, &smp->preq[1], 3); 14628c2ecf20Sopenharmony_ci } else { 14638c2ecf20Sopenharmony_ci local_addr = b; 14648c2ecf20Sopenharmony_ci remote_addr = a; 14658c2ecf20Sopenharmony_ci memcpy(io_cap, &smp->prsp[1], 3); 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci memset(r, 0, sizeof(r)); 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) 14718c2ecf20Sopenharmony_ci put_unaligned_le32(hcon->passkey_notify, r); 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (smp->method == REQ_OOB) 14748c2ecf20Sopenharmony_ci memcpy(r, smp->rr, 16); 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap, 14778c2ecf20Sopenharmony_ci local_addr, remote_addr, check.e); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check); 14808c2ecf20Sopenharmony_ci} 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_cistatic u8 sc_passkey_send_confirm(struct smp_chan *smp) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 14858c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 14868c2ecf20Sopenharmony_ci struct smp_cmd_pairing_confirm cfm; 14878c2ecf20Sopenharmony_ci u8 r; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01); 14908c2ecf20Sopenharmony_ci r |= 0x80; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci get_random_bytes(smp->prnd, sizeof(smp->prnd)); 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r, 14958c2ecf20Sopenharmony_ci cfm.confirm_val)) 14968c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci return 0; 15018c2ecf20Sopenharmony_ci} 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cistatic u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) 15048c2ecf20Sopenharmony_ci{ 15058c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 15068c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 15078c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 15088c2ecf20Sopenharmony_ci u8 cfm[16], r; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci /* Ignore the PDU if we've already done 20 rounds (0 - 19) */ 15118c2ecf20Sopenharmony_ci if (smp->passkey_round >= 20) 15128c2ecf20Sopenharmony_ci return 0; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci switch (smp_op) { 15158c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_RANDOM: 15168c2ecf20Sopenharmony_ci r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01); 15178c2ecf20Sopenharmony_ci r |= 0x80; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, 15208c2ecf20Sopenharmony_ci smp->rrnd, r, cfm)) 15218c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci if (crypto_memneq(smp->pcnf, cfm, 16)) 15248c2ecf20Sopenharmony_ci return SMP_CONFIRM_FAILED; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci smp->passkey_round++; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci if (smp->passkey_round == 20) { 15298c2ecf20Sopenharmony_ci /* Generate MacKey and LTK */ 15308c2ecf20Sopenharmony_ci if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk)) 15318c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci /* The round is only complete when the initiator 15358c2ecf20Sopenharmony_ci * receives pairing random. 15368c2ecf20Sopenharmony_ci */ 15378c2ecf20Sopenharmony_ci if (!hcon->out) { 15388c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 15398c2ecf20Sopenharmony_ci sizeof(smp->prnd), smp->prnd); 15408c2ecf20Sopenharmony_ci if (smp->passkey_round == 20) 15418c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 15428c2ecf20Sopenharmony_ci else 15438c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 15448c2ecf20Sopenharmony_ci return 0; 15458c2ecf20Sopenharmony_ci } 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci /* Start the next round */ 15488c2ecf20Sopenharmony_ci if (smp->passkey_round != 20) 15498c2ecf20Sopenharmony_ci return sc_passkey_round(smp, 0); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci /* Passkey rounds are complete - start DHKey Check */ 15528c2ecf20Sopenharmony_ci sc_dhkey_check(smp); 15538c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_CONFIRM: 15588c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) { 15598c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CFM_PENDING, &smp->flags); 15608c2ecf20Sopenharmony_ci return 0; 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci if (hcon->out) { 15668c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 15678c2ecf20Sopenharmony_ci sizeof(smp->prnd), smp->prnd); 15688c2ecf20Sopenharmony_ci return 0; 15698c2ecf20Sopenharmony_ci } 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci return sc_passkey_send_confirm(smp); 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci case SMP_CMD_PUBLIC_KEY: 15748c2ecf20Sopenharmony_ci default: 15758c2ecf20Sopenharmony_ci /* Initiating device starts the round */ 15768c2ecf20Sopenharmony_ci if (!hcon->out) 15778c2ecf20Sopenharmony_ci return 0; 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Starting passkey round %u", 15808c2ecf20Sopenharmony_ci smp->passkey_round + 1); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci return sc_passkey_send_confirm(smp); 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci return 0; 15888c2ecf20Sopenharmony_ci} 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cistatic int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) 15918c2ecf20Sopenharmony_ci{ 15928c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 15938c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 15948c2ecf20Sopenharmony_ci u8 smp_op; 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci clear_bit(SMP_FLAG_WAIT_USER, &smp->flags); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci switch (mgmt_op) { 15998c2ecf20Sopenharmony_ci case MGMT_OP_USER_PASSKEY_NEG_REPLY: 16008c2ecf20Sopenharmony_ci smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED); 16018c2ecf20Sopenharmony_ci return 0; 16028c2ecf20Sopenharmony_ci case MGMT_OP_USER_CONFIRM_NEG_REPLY: 16038c2ecf20Sopenharmony_ci smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED); 16048c2ecf20Sopenharmony_ci return 0; 16058c2ecf20Sopenharmony_ci case MGMT_OP_USER_PASSKEY_REPLY: 16068c2ecf20Sopenharmony_ci hcon->passkey_notify = le32_to_cpu(passkey); 16078c2ecf20Sopenharmony_ci smp->passkey_round = 0; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci if (test_and_clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags)) 16108c2ecf20Sopenharmony_ci smp_op = SMP_CMD_PAIRING_CONFIRM; 16118c2ecf20Sopenharmony_ci else 16128c2ecf20Sopenharmony_ci smp_op = 0; 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci if (sc_passkey_round(smp, smp_op)) 16158c2ecf20Sopenharmony_ci return -EIO; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci return 0; 16188c2ecf20Sopenharmony_ci } 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* Initiator sends DHKey check first */ 16218c2ecf20Sopenharmony_ci if (hcon->out) { 16228c2ecf20Sopenharmony_ci sc_dhkey_check(smp); 16238c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 16248c2ecf20Sopenharmony_ci } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) { 16258c2ecf20Sopenharmony_ci sc_dhkey_check(smp); 16268c2ecf20Sopenharmony_ci sc_add_ltk(smp); 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci return 0; 16308c2ecf20Sopenharmony_ci} 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ciint smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) 16338c2ecf20Sopenharmony_ci{ 16348c2ecf20Sopenharmony_ci struct l2cap_conn *conn = hcon->l2cap_data; 16358c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 16368c2ecf20Sopenharmony_ci struct smp_chan *smp; 16378c2ecf20Sopenharmony_ci u32 value; 16388c2ecf20Sopenharmony_ci int err; 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, ""); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci if (!conn) 16438c2ecf20Sopenharmony_ci return -ENOTCONN; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci chan = conn->smp; 16468c2ecf20Sopenharmony_ci if (!chan) 16478c2ecf20Sopenharmony_ci return -ENOTCONN; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci l2cap_chan_lock(chan); 16508c2ecf20Sopenharmony_ci if (!chan->data) { 16518c2ecf20Sopenharmony_ci err = -ENOTCONN; 16528c2ecf20Sopenharmony_ci goto unlock; 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci smp = chan->data; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) { 16588c2ecf20Sopenharmony_ci err = sc_user_reply(smp, mgmt_op, passkey); 16598c2ecf20Sopenharmony_ci goto unlock; 16608c2ecf20Sopenharmony_ci } 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci switch (mgmt_op) { 16638c2ecf20Sopenharmony_ci case MGMT_OP_USER_PASSKEY_REPLY: 16648c2ecf20Sopenharmony_ci value = le32_to_cpu(passkey); 16658c2ecf20Sopenharmony_ci memset(smp->tk, 0, sizeof(smp->tk)); 16668c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "PassKey: %d", value); 16678c2ecf20Sopenharmony_ci put_unaligned_le32(value, smp->tk); 16688c2ecf20Sopenharmony_ci fallthrough; 16698c2ecf20Sopenharmony_ci case MGMT_OP_USER_CONFIRM_REPLY: 16708c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_TK_VALID, &smp->flags); 16718c2ecf20Sopenharmony_ci break; 16728c2ecf20Sopenharmony_ci case MGMT_OP_USER_PASSKEY_NEG_REPLY: 16738c2ecf20Sopenharmony_ci case MGMT_OP_USER_CONFIRM_NEG_REPLY: 16748c2ecf20Sopenharmony_ci smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); 16758c2ecf20Sopenharmony_ci err = 0; 16768c2ecf20Sopenharmony_ci goto unlock; 16778c2ecf20Sopenharmony_ci default: 16788c2ecf20Sopenharmony_ci smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); 16798c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 16808c2ecf20Sopenharmony_ci goto unlock; 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci err = 0; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci /* If it is our turn to send Pairing Confirm, do so now */ 16868c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_CFM_PENDING, &smp->flags)) { 16878c2ecf20Sopenharmony_ci u8 rsp = smp_confirm(smp); 16888c2ecf20Sopenharmony_ci if (rsp) 16898c2ecf20Sopenharmony_ci smp_failure(conn, rsp); 16908c2ecf20Sopenharmony_ci } 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ciunlock: 16938c2ecf20Sopenharmony_ci l2cap_chan_unlock(chan); 16948c2ecf20Sopenharmony_ci return err; 16958c2ecf20Sopenharmony_ci} 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_cistatic void build_bredr_pairing_cmd(struct smp_chan *smp, 16988c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req, 16998c2ecf20Sopenharmony_ci struct smp_cmd_pairing *rsp) 17008c2ecf20Sopenharmony_ci{ 17018c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 17028c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hcon->hdev; 17038c2ecf20Sopenharmony_ci u8 local_dist = 0, remote_dist = 0; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_BONDABLE)) { 17068c2ecf20Sopenharmony_ci local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; 17078c2ecf20Sopenharmony_ci remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING)) 17118c2ecf20Sopenharmony_ci remote_dist |= SMP_DIST_ID_KEY; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PRIVACY)) 17148c2ecf20Sopenharmony_ci local_dist |= SMP_DIST_ID_KEY; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci if (!rsp) { 17178c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci req->auth_req = SMP_AUTH_CT2; 17208c2ecf20Sopenharmony_ci req->init_key_dist = local_dist; 17218c2ecf20Sopenharmony_ci req->resp_key_dist = remote_dist; 17228c2ecf20Sopenharmony_ci req->max_key_size = conn->hcon->enc_key_size; 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci smp->remote_key_dist = remote_dist; 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci return; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci memset(rsp, 0, sizeof(*rsp)); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci rsp->auth_req = SMP_AUTH_CT2; 17328c2ecf20Sopenharmony_ci rsp->max_key_size = conn->hcon->enc_key_size; 17338c2ecf20Sopenharmony_ci rsp->init_key_dist = req->init_key_dist & remote_dist; 17348c2ecf20Sopenharmony_ci rsp->resp_key_dist = req->resp_key_dist & local_dist; 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci smp->remote_key_dist = rsp->init_key_dist; 17378c2ecf20Sopenharmony_ci} 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_cistatic u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 17408c2ecf20Sopenharmony_ci{ 17418c2ecf20Sopenharmony_ci struct smp_cmd_pairing rsp, *req = (void *) skb->data; 17428c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 17438c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hcon->hdev; 17448c2ecf20Sopenharmony_ci struct smp_chan *smp; 17458c2ecf20Sopenharmony_ci u8 key_size, auth, sec_level; 17468c2ecf20Sopenharmony_ci int ret; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci if (skb->len < sizeof(*req)) 17518c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci if (conn->hcon->role != HCI_ROLE_SLAVE) 17548c2ecf20Sopenharmony_ci return SMP_CMD_NOTSUPP; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if (!chan->data) 17578c2ecf20Sopenharmony_ci smp = smp_chan_create(conn); 17588c2ecf20Sopenharmony_ci else 17598c2ecf20Sopenharmony_ci smp = chan->data; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci if (!smp) 17628c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci /* We didn't start the pairing, so match remote */ 17658c2ecf20Sopenharmony_ci auth = req->auth_req & AUTH_REQ_MASK(hdev); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BONDABLE) && 17688c2ecf20Sopenharmony_ci (auth & SMP_AUTH_BONDING)) 17698c2ecf20Sopenharmony_ci return SMP_PAIRING_NOTSUPP; 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC)) 17728c2ecf20Sopenharmony_ci return SMP_AUTH_REQUIREMENTS; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci smp->preq[0] = SMP_CMD_PAIRING_REQ; 17758c2ecf20Sopenharmony_ci memcpy(&smp->preq[1], req, sizeof(*req)); 17768c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*req)); 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci /* If the remote side's OOB flag is set it means it has 17798c2ecf20Sopenharmony_ci * successfully received our local OOB data - therefore set the 17808c2ecf20Sopenharmony_ci * flag to indicate that local OOB is in use. 17818c2ecf20Sopenharmony_ci */ 17828c2ecf20Sopenharmony_ci if (req->oob_flag == SMP_OOB_PRESENT && SMP_DEV(hdev)->local_oob) 17838c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags); 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci /* SMP over BR/EDR requires special treatment */ 17868c2ecf20Sopenharmony_ci if (conn->hcon->type == ACL_LINK) { 17878c2ecf20Sopenharmony_ci /* We must have a BR/EDR SC link */ 17888c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) && 17898c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) 17908c2ecf20Sopenharmony_ci return SMP_CROSS_TRANSP_NOT_ALLOWED; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_SC, &smp->flags); 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci build_bredr_pairing_cmd(smp, req, &rsp); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci if (req->auth_req & SMP_AUTH_CT2) 17978c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CT2, &smp->flags); 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci key_size = min(req->max_key_size, rsp.max_key_size); 18008c2ecf20Sopenharmony_ci if (check_enc_key_size(conn, key_size)) 18018c2ecf20Sopenharmony_ci return SMP_ENC_KEY_SIZE; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci /* Clear bits which are generated but not distributed */ 18048c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_SC_NO_DIST; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci smp->prsp[0] = SMP_CMD_PAIRING_RSP; 18078c2ecf20Sopenharmony_ci memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 18088c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 18118c2ecf20Sopenharmony_ci return 0; 18128c2ecf20Sopenharmony_ci } 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci build_pairing_cmd(conn, req, &rsp, auth); 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci if (rsp.auth_req & SMP_AUTH_SC) { 18178c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_SC, &smp->flags); 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci if (rsp.auth_req & SMP_AUTH_CT2) 18208c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CT2, &smp->flags); 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) 18248c2ecf20Sopenharmony_ci sec_level = BT_SECURITY_MEDIUM; 18258c2ecf20Sopenharmony_ci else 18268c2ecf20Sopenharmony_ci sec_level = authreq_to_seclevel(auth); 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci if (sec_level > conn->hcon->pending_sec_level) 18298c2ecf20Sopenharmony_ci conn->hcon->pending_sec_level = sec_level; 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci /* If we need MITM check that it can be achieved */ 18328c2ecf20Sopenharmony_ci if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) { 18338c2ecf20Sopenharmony_ci u8 method; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci method = get_auth_method(smp, conn->hcon->io_capability, 18368c2ecf20Sopenharmony_ci req->io_capability); 18378c2ecf20Sopenharmony_ci if (method == JUST_WORKS || method == JUST_CFM) 18388c2ecf20Sopenharmony_ci return SMP_AUTH_REQUIREMENTS; 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci key_size = min(req->max_key_size, rsp.max_key_size); 18428c2ecf20Sopenharmony_ci if (check_enc_key_size(conn, key_size)) 18438c2ecf20Sopenharmony_ci return SMP_ENC_KEY_SIZE; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci get_random_bytes(smp->prnd, sizeof(smp->prnd)); 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci smp->prsp[0] = SMP_CMD_PAIRING_RSP; 18488c2ecf20Sopenharmony_ci memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci clear_bit(SMP_FLAG_INITIATOR, &smp->flags); 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci /* Strictly speaking we shouldn't allow Pairing Confirm for the 18558c2ecf20Sopenharmony_ci * SC case, however some implementations incorrectly copy RFU auth 18568c2ecf20Sopenharmony_ci * req bits from our security request, which may create a false 18578c2ecf20Sopenharmony_ci * positive SC enablement. 18588c2ecf20Sopenharmony_ci */ 18598c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) { 18628c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY); 18638c2ecf20Sopenharmony_ci /* Clear bits which are generated but not distributed */ 18648c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_SC_NO_DIST; 18658c2ecf20Sopenharmony_ci /* Wait for Public Key from Initiating Device */ 18668c2ecf20Sopenharmony_ci return 0; 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci /* Request setup of TK */ 18708c2ecf20Sopenharmony_ci ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); 18718c2ecf20Sopenharmony_ci if (ret) 18728c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci return 0; 18758c2ecf20Sopenharmony_ci} 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_cistatic u8 sc_send_public_key(struct smp_chan *smp) 18788c2ecf20Sopenharmony_ci{ 18798c2ecf20Sopenharmony_ci struct hci_dev *hdev = smp->conn->hcon->hdev; 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, ""); 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) { 18848c2ecf20Sopenharmony_ci struct l2cap_chan *chan = hdev->smp_data; 18858c2ecf20Sopenharmony_ci struct smp_dev *smp_dev; 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci if (!chan || !chan->data) 18888c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci smp_dev = chan->data; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci memcpy(smp->local_pk, smp_dev->local_pk, 64); 18938c2ecf20Sopenharmony_ci memcpy(smp->lr, smp_dev->local_rand, 16); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci if (smp_dev->debug_key) 18968c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci goto done; 18998c2ecf20Sopenharmony_ci } 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) { 19028c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Using debug keys"); 19038c2ecf20Sopenharmony_ci if (set_ecdh_privkey(smp->tfm_ecdh, debug_sk)) 19048c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 19058c2ecf20Sopenharmony_ci memcpy(smp->local_pk, debug_pk, 64); 19068c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); 19078c2ecf20Sopenharmony_ci } else { 19088c2ecf20Sopenharmony_ci while (true) { 19098c2ecf20Sopenharmony_ci /* Generate key pair for Secure Connections */ 19108c2ecf20Sopenharmony_ci if (generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk)) 19118c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci /* This is unlikely, but we need to check that 19148c2ecf20Sopenharmony_ci * we didn't accidentially generate a debug key. 19158c2ecf20Sopenharmony_ci */ 19168c2ecf20Sopenharmony_ci if (crypto_memneq(smp->local_pk, debug_pk, 64)) 19178c2ecf20Sopenharmony_ci break; 19188c2ecf20Sopenharmony_ci } 19198c2ecf20Sopenharmony_ci } 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_cidone: 19228c2ecf20Sopenharmony_ci SMP_DBG("Local Public Key X: %32phN", smp->local_pk); 19238c2ecf20Sopenharmony_ci SMP_DBG("Local Public Key Y: %32phN", smp->local_pk + 32); 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci return 0; 19288c2ecf20Sopenharmony_ci} 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_cistatic u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 19318c2ecf20Sopenharmony_ci{ 19328c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req, *rsp = (void *) skb->data; 19338c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 19348c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 19358c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hcon->hdev; 19368c2ecf20Sopenharmony_ci u8 key_size, auth; 19378c2ecf20Sopenharmony_ci int ret; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rsp)) 19428c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci if (conn->hcon->role != HCI_ROLE_MASTER) 19458c2ecf20Sopenharmony_ci return SMP_CMD_NOTSUPP; 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*rsp)); 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ci req = (void *) &smp->preq[1]; 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci key_size = min(req->max_key_size, rsp->max_key_size); 19528c2ecf20Sopenharmony_ci if (check_enc_key_size(conn, key_size)) 19538c2ecf20Sopenharmony_ci return SMP_ENC_KEY_SIZE; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci auth = rsp->auth_req & AUTH_REQ_MASK(hdev); 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC)) 19588c2ecf20Sopenharmony_ci return SMP_AUTH_REQUIREMENTS; 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci /* If the remote side's OOB flag is set it means it has 19618c2ecf20Sopenharmony_ci * successfully received our local OOB data - therefore set the 19628c2ecf20Sopenharmony_ci * flag to indicate that local OOB is in use. 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci if (rsp->oob_flag == SMP_OOB_PRESENT && SMP_DEV(hdev)->local_oob) 19658c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags); 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci smp->prsp[0] = SMP_CMD_PAIRING_RSP; 19688c2ecf20Sopenharmony_ci memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci /* Update remote key distribution in case the remote cleared 19718c2ecf20Sopenharmony_ci * some bits that we had enabled in our request. 19728c2ecf20Sopenharmony_ci */ 19738c2ecf20Sopenharmony_ci smp->remote_key_dist &= rsp->resp_key_dist; 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2)) 19768c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CT2, &smp->flags); 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci /* For BR/EDR this means we're done and can start phase 3 */ 19798c2ecf20Sopenharmony_ci if (conn->hcon->type == ACL_LINK) { 19808c2ecf20Sopenharmony_ci /* Clear bits which are generated but not distributed */ 19818c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_SC_NO_DIST; 19828c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 19838c2ecf20Sopenharmony_ci return 0; 19848c2ecf20Sopenharmony_ci } 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC)) 19878c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_SC, &smp->flags); 19888c2ecf20Sopenharmony_ci else if (conn->hcon->pending_sec_level > BT_SECURITY_HIGH) 19898c2ecf20Sopenharmony_ci conn->hcon->pending_sec_level = BT_SECURITY_HIGH; 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci /* If we need MITM check that it can be achieved */ 19928c2ecf20Sopenharmony_ci if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) { 19938c2ecf20Sopenharmony_ci u8 method; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci method = get_auth_method(smp, req->io_capability, 19968c2ecf20Sopenharmony_ci rsp->io_capability); 19978c2ecf20Sopenharmony_ci if (method == JUST_WORKS || method == JUST_CFM) 19988c2ecf20Sopenharmony_ci return SMP_AUTH_REQUIREMENTS; 19998c2ecf20Sopenharmony_ci } 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci get_random_bytes(smp->prnd, sizeof(smp->prnd)); 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci /* Update remote key distribution in case the remote cleared 20048c2ecf20Sopenharmony_ci * some bits that we had enabled in our request. 20058c2ecf20Sopenharmony_ci */ 20068c2ecf20Sopenharmony_ci smp->remote_key_dist &= rsp->resp_key_dist; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) { 20098c2ecf20Sopenharmony_ci /* Clear bits which are generated but not distributed */ 20108c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_SC_NO_DIST; 20118c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY); 20128c2ecf20Sopenharmony_ci return sc_send_public_key(smp); 20138c2ecf20Sopenharmony_ci } 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci auth |= req->auth_req; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); 20188c2ecf20Sopenharmony_ci if (ret) 20198c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CFM_PENDING, &smp->flags); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci /* Can't compose response until we have been confirmed */ 20248c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_TK_VALID, &smp->flags)) 20258c2ecf20Sopenharmony_ci return smp_confirm(smp); 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci return 0; 20288c2ecf20Sopenharmony_ci} 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_cistatic u8 sc_check_confirm(struct smp_chan *smp) 20318c2ecf20Sopenharmony_ci{ 20328c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, ""); 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) 20378c2ecf20Sopenharmony_ci return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM); 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci if (conn->hcon->out) { 20408c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), 20418c2ecf20Sopenharmony_ci smp->prnd); 20428c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 20438c2ecf20Sopenharmony_ci } 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci return 0; 20468c2ecf20Sopenharmony_ci} 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci/* Work-around for some implementations that incorrectly copy RFU bits 20498c2ecf20Sopenharmony_ci * from our security request and thereby create the impression that 20508c2ecf20Sopenharmony_ci * we're doing SC when in fact the remote doesn't support it. 20518c2ecf20Sopenharmony_ci */ 20528c2ecf20Sopenharmony_cistatic int fixup_sc_false_positive(struct smp_chan *smp) 20538c2ecf20Sopenharmony_ci{ 20548c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 20558c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 20568c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 20578c2ecf20Sopenharmony_ci struct smp_cmd_pairing *req, *rsp; 20588c2ecf20Sopenharmony_ci u8 auth; 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci /* The issue is only observed when we're in responder role */ 20618c2ecf20Sopenharmony_ci if (hcon->out) 20628c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) { 20658c2ecf20Sopenharmony_ci bt_dev_err(hdev, "refusing legacy fallback in SC-only mode"); 20668c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 20678c2ecf20Sopenharmony_ci } 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci bt_dev_err(hdev, "trying to fall back to legacy SMP"); 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci req = (void *) &smp->preq[1]; 20728c2ecf20Sopenharmony_ci rsp = (void *) &smp->prsp[1]; 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci /* Rebuild key dist flags which may have been cleared for SC */ 20758c2ecf20Sopenharmony_ci smp->remote_key_dist = (req->init_key_dist & rsp->resp_key_dist); 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci auth = req->auth_req & AUTH_REQ_MASK(hdev); 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci if (tk_request(conn, 0, auth, rsp->io_capability, req->io_capability)) { 20808c2ecf20Sopenharmony_ci bt_dev_err(hdev, "failed to fall back to legacy SMP"); 20818c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci clear_bit(SMP_FLAG_SC, &smp->flags); 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci return 0; 20878c2ecf20Sopenharmony_ci} 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_cistatic u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) 20908c2ecf20Sopenharmony_ci{ 20918c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 20928c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 20938c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 20948c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p %s", conn, 20978c2ecf20Sopenharmony_ci hcon->out ? "initiator" : "responder"); 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci if (skb->len < sizeof(smp->pcnf)) 21008c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); 21038c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(smp->pcnf)); 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_SC, &smp->flags)) { 21068c2ecf20Sopenharmony_ci int ret; 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci /* Public Key exchange must happen before any other steps */ 21098c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_REMOTE_PK, &smp->flags)) 21108c2ecf20Sopenharmony_ci return sc_check_confirm(smp); 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Unexpected SMP Pairing Confirm"); 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci ret = fixup_sc_false_positive(smp); 21158c2ecf20Sopenharmony_ci if (ret) 21168c2ecf20Sopenharmony_ci return ret; 21178c2ecf20Sopenharmony_ci } 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci if (conn->hcon->out) { 21208c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), 21218c2ecf20Sopenharmony_ci smp->prnd); 21228c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 21238c2ecf20Sopenharmony_ci return 0; 21248c2ecf20Sopenharmony_ci } 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_TK_VALID, &smp->flags)) 21278c2ecf20Sopenharmony_ci return smp_confirm(smp); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_CFM_PENDING, &smp->flags); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci return 0; 21328c2ecf20Sopenharmony_ci} 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_cistatic u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 21358c2ecf20Sopenharmony_ci{ 21368c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 21378c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 21388c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 21398c2ecf20Sopenharmony_ci u8 *pkax, *pkbx, *na, *nb, confirm_hint; 21408c2ecf20Sopenharmony_ci u32 passkey; 21418c2ecf20Sopenharmony_ci int err; 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "conn %p", conn); 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci if (skb->len < sizeof(smp->rrnd)) 21468c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd)); 21498c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(smp->rrnd)); 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci if (!test_bit(SMP_FLAG_SC, &smp->flags)) 21528c2ecf20Sopenharmony_ci return smp_random(smp); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci if (hcon->out) { 21558c2ecf20Sopenharmony_ci pkax = smp->local_pk; 21568c2ecf20Sopenharmony_ci pkbx = smp->remote_pk; 21578c2ecf20Sopenharmony_ci na = smp->prnd; 21588c2ecf20Sopenharmony_ci nb = smp->rrnd; 21598c2ecf20Sopenharmony_ci } else { 21608c2ecf20Sopenharmony_ci pkax = smp->remote_pk; 21618c2ecf20Sopenharmony_ci pkbx = smp->local_pk; 21628c2ecf20Sopenharmony_ci na = smp->rrnd; 21638c2ecf20Sopenharmony_ci nb = smp->prnd; 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci if (smp->method == REQ_OOB) { 21678c2ecf20Sopenharmony_ci if (!hcon->out) 21688c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 21698c2ecf20Sopenharmony_ci sizeof(smp->prnd), smp->prnd); 21708c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 21718c2ecf20Sopenharmony_ci goto mackey_and_ltk; 21728c2ecf20Sopenharmony_ci } 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci /* Passkey entry has special treatment */ 21758c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) 21768c2ecf20Sopenharmony_ci return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM); 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci if (hcon->out) { 21798c2ecf20Sopenharmony_ci u8 cfm[16]; 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, 21828c2ecf20Sopenharmony_ci smp->rrnd, 0, cfm); 21838c2ecf20Sopenharmony_ci if (err) 21848c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci if (crypto_memneq(smp->pcnf, cfm, 16)) 21878c2ecf20Sopenharmony_ci return SMP_CONFIRM_FAILED; 21888c2ecf20Sopenharmony_ci } else { 21898c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), 21908c2ecf20Sopenharmony_ci smp->prnd); 21918c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci /* Only Just-Works pairing requires extra checks */ 21948c2ecf20Sopenharmony_ci if (smp->method != JUST_WORKS) 21958c2ecf20Sopenharmony_ci goto mackey_and_ltk; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci /* If there already exists long term key in local host, leave 21988c2ecf20Sopenharmony_ci * the decision to user space since the remote device could 21998c2ecf20Sopenharmony_ci * be legitimate or malicious. 22008c2ecf20Sopenharmony_ci */ 22018c2ecf20Sopenharmony_ci if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, 22028c2ecf20Sopenharmony_ci hcon->role)) { 22038c2ecf20Sopenharmony_ci /* Set passkey to 0. The value can be any number since 22048c2ecf20Sopenharmony_ci * it'll be ignored anyway. 22058c2ecf20Sopenharmony_ci */ 22068c2ecf20Sopenharmony_ci passkey = 0; 22078c2ecf20Sopenharmony_ci confirm_hint = 1; 22088c2ecf20Sopenharmony_ci goto confirm; 22098c2ecf20Sopenharmony_ci } 22108c2ecf20Sopenharmony_ci } 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_cimackey_and_ltk: 22138c2ecf20Sopenharmony_ci /* Generate MacKey and LTK */ 22148c2ecf20Sopenharmony_ci err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk); 22158c2ecf20Sopenharmony_ci if (err) 22168c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci if (smp->method == REQ_OOB) { 22198c2ecf20Sopenharmony_ci if (hcon->out) { 22208c2ecf20Sopenharmony_ci sc_dhkey_check(smp); 22218c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); 22228c2ecf20Sopenharmony_ci } 22238c2ecf20Sopenharmony_ci return 0; 22248c2ecf20Sopenharmony_ci } 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey); 22278c2ecf20Sopenharmony_ci if (err) 22288c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ci confirm_hint = 0; 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ciconfirm: 22338c2ecf20Sopenharmony_ci if (smp->method == JUST_WORKS) 22348c2ecf20Sopenharmony_ci confirm_hint = 1; 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, 22378c2ecf20Sopenharmony_ci hcon->dst_type, passkey, confirm_hint); 22388c2ecf20Sopenharmony_ci if (err) 22398c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_WAIT_USER, &smp->flags); 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci return 0; 22448c2ecf20Sopenharmony_ci} 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_cistatic bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) 22478c2ecf20Sopenharmony_ci{ 22488c2ecf20Sopenharmony_ci struct smp_ltk *key; 22498c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci key = hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role); 22528c2ecf20Sopenharmony_ci if (!key) 22538c2ecf20Sopenharmony_ci return false; 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_ci if (smp_ltk_sec_level(key) < sec_level) 22568c2ecf20Sopenharmony_ci return false; 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) 22598c2ecf20Sopenharmony_ci return true; 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci hci_le_start_enc(hcon, key->ediv, key->rand, key->val, key->enc_size); 22628c2ecf20Sopenharmony_ci hcon->enc_key_size = key->enc_size; 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_ci /* We never store STKs for initiator role, so clear this flag */ 22658c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags); 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci return true; 22688c2ecf20Sopenharmony_ci} 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_cibool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level, 22718c2ecf20Sopenharmony_ci enum smp_key_pref key_pref) 22728c2ecf20Sopenharmony_ci{ 22738c2ecf20Sopenharmony_ci if (sec_level == BT_SECURITY_LOW) 22748c2ecf20Sopenharmony_ci return true; 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci /* If we're encrypted with an STK but the caller prefers using 22778c2ecf20Sopenharmony_ci * LTK claim insufficient security. This way we allow the 22788c2ecf20Sopenharmony_ci * connection to be re-encrypted with an LTK, even if the LTK 22798c2ecf20Sopenharmony_ci * provides the same level of security. Only exception is if we 22808c2ecf20Sopenharmony_ci * don't have an LTK (e.g. because of key distribution bits). 22818c2ecf20Sopenharmony_ci */ 22828c2ecf20Sopenharmony_ci if (key_pref == SMP_USE_LTK && 22838c2ecf20Sopenharmony_ci test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && 22848c2ecf20Sopenharmony_ci hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role)) 22858c2ecf20Sopenharmony_ci return false; 22868c2ecf20Sopenharmony_ci 22878c2ecf20Sopenharmony_ci if (hcon->sec_level >= sec_level) 22888c2ecf20Sopenharmony_ci return true; 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci return false; 22918c2ecf20Sopenharmony_ci} 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_cistatic u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) 22948c2ecf20Sopenharmony_ci{ 22958c2ecf20Sopenharmony_ci struct smp_cmd_security_req *rp = (void *) skb->data; 22968c2ecf20Sopenharmony_ci struct smp_cmd_pairing cp; 22978c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 22988c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 22998c2ecf20Sopenharmony_ci struct smp_chan *smp; 23008c2ecf20Sopenharmony_ci u8 sec_level, auth; 23018c2ecf20Sopenharmony_ci 23028c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 23038c2ecf20Sopenharmony_ci 23048c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rp)) 23058c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci if (hcon->role != HCI_ROLE_MASTER) 23088c2ecf20Sopenharmony_ci return SMP_CMD_NOTSUPP; 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci auth = rp->auth_req & AUTH_REQ_MASK(hdev); 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC)) 23138c2ecf20Sopenharmony_ci return SMP_AUTH_REQUIREMENTS; 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) 23168c2ecf20Sopenharmony_ci sec_level = BT_SECURITY_MEDIUM; 23178c2ecf20Sopenharmony_ci else 23188c2ecf20Sopenharmony_ci sec_level = authreq_to_seclevel(auth); 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) { 23218c2ecf20Sopenharmony_ci /* If link is already encrypted with sufficient security we 23228c2ecf20Sopenharmony_ci * still need refresh encryption as per Core Spec 5.0 Vol 3, 23238c2ecf20Sopenharmony_ci * Part H 2.4.6 23248c2ecf20Sopenharmony_ci */ 23258c2ecf20Sopenharmony_ci smp_ltk_encrypt(conn, hcon->sec_level); 23268c2ecf20Sopenharmony_ci return 0; 23278c2ecf20Sopenharmony_ci } 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci if (sec_level > hcon->pending_sec_level) 23308c2ecf20Sopenharmony_ci hcon->pending_sec_level = sec_level; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) 23338c2ecf20Sopenharmony_ci return 0; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci smp = smp_chan_create(conn); 23368c2ecf20Sopenharmony_ci if (!smp) 23378c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BONDABLE) && 23408c2ecf20Sopenharmony_ci (auth & SMP_AUTH_BONDING)) 23418c2ecf20Sopenharmony_ci return SMP_PAIRING_NOTSUPP; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*rp)); 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 23468c2ecf20Sopenharmony_ci build_pairing_cmd(conn, &cp, NULL, auth); 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci smp->preq[0] = SMP_CMD_PAIRING_REQ; 23498c2ecf20Sopenharmony_ci memcpy(&smp->preq[1], &cp, sizeof(cp)); 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 23528c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci return 0; 23558c2ecf20Sopenharmony_ci} 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ciint smp_conn_security(struct hci_conn *hcon, __u8 sec_level) 23588c2ecf20Sopenharmony_ci{ 23598c2ecf20Sopenharmony_ci struct l2cap_conn *conn = hcon->l2cap_data; 23608c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 23618c2ecf20Sopenharmony_ci struct smp_chan *smp; 23628c2ecf20Sopenharmony_ci __u8 authreq; 23638c2ecf20Sopenharmony_ci int ret; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "conn %p hcon %p level 0x%2.2x", conn, hcon, 23668c2ecf20Sopenharmony_ci sec_level); 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci /* This may be NULL if there's an unexpected disconnection */ 23698c2ecf20Sopenharmony_ci if (!conn) 23708c2ecf20Sopenharmony_ci return 1; 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) 23738c2ecf20Sopenharmony_ci return 1; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) 23768c2ecf20Sopenharmony_ci return 1; 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci if (sec_level > hcon->pending_sec_level) 23798c2ecf20Sopenharmony_ci hcon->pending_sec_level = sec_level; 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci if (hcon->role == HCI_ROLE_MASTER) 23828c2ecf20Sopenharmony_ci if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) 23838c2ecf20Sopenharmony_ci return 0; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci chan = conn->smp; 23868c2ecf20Sopenharmony_ci if (!chan) { 23878c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "security requested but not available"); 23888c2ecf20Sopenharmony_ci return 1; 23898c2ecf20Sopenharmony_ci } 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci l2cap_chan_lock(chan); 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci /* If SMP is already in progress ignore this request */ 23948c2ecf20Sopenharmony_ci if (chan->data) { 23958c2ecf20Sopenharmony_ci ret = 0; 23968c2ecf20Sopenharmony_ci goto unlock; 23978c2ecf20Sopenharmony_ci } 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci smp = smp_chan_create(conn); 24008c2ecf20Sopenharmony_ci if (!smp) { 24018c2ecf20Sopenharmony_ci ret = 1; 24028c2ecf20Sopenharmony_ci goto unlock; 24038c2ecf20Sopenharmony_ci } 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci authreq = seclevel_to_authreq(sec_level); 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) { 24088c2ecf20Sopenharmony_ci authreq |= SMP_AUTH_SC; 24098c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED)) 24108c2ecf20Sopenharmony_ci authreq |= SMP_AUTH_CT2; 24118c2ecf20Sopenharmony_ci } 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci /* Don't attempt to set MITM if setting is overridden by debugfs 24148c2ecf20Sopenharmony_ci * Needed to pass certification test SM/MAS/PKE/BV-01-C 24158c2ecf20Sopenharmony_ci */ 24168c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hcon->hdev, HCI_FORCE_NO_MITM)) { 24178c2ecf20Sopenharmony_ci /* Require MITM if IO Capability allows or the security level 24188c2ecf20Sopenharmony_ci * requires it. 24198c2ecf20Sopenharmony_ci */ 24208c2ecf20Sopenharmony_ci if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT || 24218c2ecf20Sopenharmony_ci hcon->pending_sec_level > BT_SECURITY_MEDIUM) 24228c2ecf20Sopenharmony_ci authreq |= SMP_AUTH_MITM; 24238c2ecf20Sopenharmony_ci } 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci if (hcon->role == HCI_ROLE_MASTER) { 24268c2ecf20Sopenharmony_ci struct smp_cmd_pairing cp; 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci build_pairing_cmd(conn, &cp, NULL, authreq); 24298c2ecf20Sopenharmony_ci smp->preq[0] = SMP_CMD_PAIRING_REQ; 24308c2ecf20Sopenharmony_ci memcpy(&smp->preq[1], &cp, sizeof(cp)); 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 24338c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); 24348c2ecf20Sopenharmony_ci } else { 24358c2ecf20Sopenharmony_ci struct smp_cmd_security_req cp; 24368c2ecf20Sopenharmony_ci cp.auth_req = authreq; 24378c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 24388c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ); 24398c2ecf20Sopenharmony_ci } 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_INITIATOR, &smp->flags); 24428c2ecf20Sopenharmony_ci ret = 0; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ciunlock: 24458c2ecf20Sopenharmony_ci l2cap_chan_unlock(chan); 24468c2ecf20Sopenharmony_ci return ret; 24478c2ecf20Sopenharmony_ci} 24488c2ecf20Sopenharmony_ci 24498c2ecf20Sopenharmony_ciint smp_cancel_and_remove_pairing(struct hci_dev *hdev, bdaddr_t *bdaddr, 24508c2ecf20Sopenharmony_ci u8 addr_type) 24518c2ecf20Sopenharmony_ci{ 24528c2ecf20Sopenharmony_ci struct hci_conn *hcon; 24538c2ecf20Sopenharmony_ci struct l2cap_conn *conn; 24548c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 24558c2ecf20Sopenharmony_ci struct smp_chan *smp; 24568c2ecf20Sopenharmony_ci int err; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci err = hci_remove_ltk(hdev, bdaddr, addr_type); 24598c2ecf20Sopenharmony_ci hci_remove_irk(hdev, bdaddr, addr_type); 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_le(hdev, bdaddr, addr_type); 24628c2ecf20Sopenharmony_ci if (!hcon) 24638c2ecf20Sopenharmony_ci goto done; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci conn = hcon->l2cap_data; 24668c2ecf20Sopenharmony_ci if (!conn) 24678c2ecf20Sopenharmony_ci goto done; 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci chan = conn->smp; 24708c2ecf20Sopenharmony_ci if (!chan) 24718c2ecf20Sopenharmony_ci goto done; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci l2cap_chan_lock(chan); 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_ci smp = chan->data; 24768c2ecf20Sopenharmony_ci if (smp) { 24778c2ecf20Sopenharmony_ci /* Set keys to NULL to make sure smp_failure() does not try to 24788c2ecf20Sopenharmony_ci * remove and free already invalidated rcu list entries. */ 24798c2ecf20Sopenharmony_ci smp->ltk = NULL; 24808c2ecf20Sopenharmony_ci smp->responder_ltk = NULL; 24818c2ecf20Sopenharmony_ci smp->remote_irk = NULL; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_COMPLETE, &smp->flags)) 24848c2ecf20Sopenharmony_ci smp_failure(conn, 0); 24858c2ecf20Sopenharmony_ci else 24868c2ecf20Sopenharmony_ci smp_failure(conn, SMP_UNSPECIFIED); 24878c2ecf20Sopenharmony_ci err = 0; 24888c2ecf20Sopenharmony_ci } 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci l2cap_chan_unlock(chan); 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_cidone: 24938c2ecf20Sopenharmony_ci return err; 24948c2ecf20Sopenharmony_ci} 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_cistatic int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) 24978c2ecf20Sopenharmony_ci{ 24988c2ecf20Sopenharmony_ci struct smp_cmd_encrypt_info *rp = (void *) skb->data; 24998c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 25008c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "conn %p", conn); 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rp)) 25058c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci /* Pairing is aborted if any blocked keys are distributed */ 25088c2ecf20Sopenharmony_ci if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_LTK, 25098c2ecf20Sopenharmony_ci rp->ltk)) { 25108c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(conn->hcon->hdev, 25118c2ecf20Sopenharmony_ci "LTK blocked for %pMR", 25128c2ecf20Sopenharmony_ci &conn->hcon->dst); 25138c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 25148c2ecf20Sopenharmony_ci } 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_INITIATOR_IDENT); 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*rp)); 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_ci return 0; 25238c2ecf20Sopenharmony_ci} 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_cistatic int smp_cmd_initiator_ident(struct l2cap_conn *conn, struct sk_buff *skb) 25268c2ecf20Sopenharmony_ci{ 25278c2ecf20Sopenharmony_ci struct smp_cmd_initiator_ident *rp = (void *)skb->data; 25288c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 25298c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 25308c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hcon->hdev; 25318c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 25328c2ecf20Sopenharmony_ci struct smp_ltk *ltk; 25338c2ecf20Sopenharmony_ci u8 authenticated; 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 25368c2ecf20Sopenharmony_ci 25378c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rp)) 25388c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci /* Mark the information as received */ 25418c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_DIST_ENC_KEY; 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci if (smp->remote_key_dist & SMP_DIST_ID_KEY) 25448c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_IDENT_INFO); 25458c2ecf20Sopenharmony_ci else if (smp->remote_key_dist & SMP_DIST_SIGN) 25468c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO); 25478c2ecf20Sopenharmony_ci 25488c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*rp)); 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci authenticated = (hcon->sec_level == BT_SECURITY_HIGH); 25518c2ecf20Sopenharmony_ci ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK, 25528c2ecf20Sopenharmony_ci authenticated, smp->tk, smp->enc_key_size, 25538c2ecf20Sopenharmony_ci rp->ediv, rp->rand); 25548c2ecf20Sopenharmony_ci smp->ltk = ltk; 25558c2ecf20Sopenharmony_ci if (!(smp->remote_key_dist & KEY_DIST_MASK)) 25568c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci return 0; 25598c2ecf20Sopenharmony_ci} 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_cistatic int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb) 25628c2ecf20Sopenharmony_ci{ 25638c2ecf20Sopenharmony_ci struct smp_cmd_ident_info *info = (void *) skb->data; 25648c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 25658c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, ""); 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci if (skb->len < sizeof(*info)) 25708c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci /* Pairing is aborted if any blocked keys are distributed */ 25738c2ecf20Sopenharmony_ci if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_IRK, 25748c2ecf20Sopenharmony_ci info->irk)) { 25758c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(conn->hcon->hdev, 25768c2ecf20Sopenharmony_ci "Identity key blocked for %pMR", 25778c2ecf20Sopenharmony_ci &conn->hcon->dst); 25788c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 25798c2ecf20Sopenharmony_ci } 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_IDENT_ADDR_INFO); 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*info)); 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci memcpy(smp->irk, info->irk, 16); 25868c2ecf20Sopenharmony_ci 25878c2ecf20Sopenharmony_ci return 0; 25888c2ecf20Sopenharmony_ci} 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_cistatic int smp_cmd_ident_addr_info(struct l2cap_conn *conn, 25918c2ecf20Sopenharmony_ci struct sk_buff *skb) 25928c2ecf20Sopenharmony_ci{ 25938c2ecf20Sopenharmony_ci struct smp_cmd_ident_addr_info *info = (void *) skb->data; 25948c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 25958c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 25968c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 25978c2ecf20Sopenharmony_ci bdaddr_t rpa; 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, ""); 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci if (skb->len < sizeof(*info)) 26028c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_ci /* Mark the information as received */ 26058c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_DIST_ID_KEY; 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci if (smp->remote_key_dist & SMP_DIST_SIGN) 26088c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO); 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*info)); 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci /* Strictly speaking the Core Specification (4.1) allows sending 26138c2ecf20Sopenharmony_ci * an empty address which would force us to rely on just the IRK 26148c2ecf20Sopenharmony_ci * as "identity information". However, since such 26158c2ecf20Sopenharmony_ci * implementations are not known of and in order to not over 26168c2ecf20Sopenharmony_ci * complicate our implementation, simply pretend that we never 26178c2ecf20Sopenharmony_ci * received an IRK for such a device. 26188c2ecf20Sopenharmony_ci * 26198c2ecf20Sopenharmony_ci * The Identity Address must also be a Static Random or Public 26208c2ecf20Sopenharmony_ci * Address, which hci_is_identity_address() checks for. 26218c2ecf20Sopenharmony_ci */ 26228c2ecf20Sopenharmony_ci if (!bacmp(&info->bdaddr, BDADDR_ANY) || 26238c2ecf20Sopenharmony_ci !hci_is_identity_address(&info->bdaddr, info->addr_type)) { 26248c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "ignoring IRK with no identity address"); 26258c2ecf20Sopenharmony_ci goto distribute; 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci /* Drop IRK if peer is using identity address during pairing but is 26298c2ecf20Sopenharmony_ci * providing different address as identity information. 26308c2ecf20Sopenharmony_ci * 26318c2ecf20Sopenharmony_ci * Microsoft Surface Precision Mouse is known to have this bug. 26328c2ecf20Sopenharmony_ci */ 26338c2ecf20Sopenharmony_ci if (hci_is_identity_address(&hcon->dst, hcon->dst_type) && 26348c2ecf20Sopenharmony_ci (bacmp(&info->bdaddr, &hcon->dst) || 26358c2ecf20Sopenharmony_ci info->addr_type != hcon->dst_type)) { 26368c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, 26378c2ecf20Sopenharmony_ci "ignoring IRK with invalid identity address"); 26388c2ecf20Sopenharmony_ci goto distribute; 26398c2ecf20Sopenharmony_ci } 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_ci bacpy(&smp->id_addr, &info->bdaddr); 26428c2ecf20Sopenharmony_ci smp->id_addr_type = info->addr_type; 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type)) 26458c2ecf20Sopenharmony_ci bacpy(&rpa, &hcon->dst); 26468c2ecf20Sopenharmony_ci else 26478c2ecf20Sopenharmony_ci bacpy(&rpa, BDADDR_ANY); 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, 26508c2ecf20Sopenharmony_ci smp->id_addr_type, smp->irk, &rpa); 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_cidistribute: 26538c2ecf20Sopenharmony_ci if (!(smp->remote_key_dist & KEY_DIST_MASK)) 26548c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 26558c2ecf20Sopenharmony_ci 26568c2ecf20Sopenharmony_ci return 0; 26578c2ecf20Sopenharmony_ci} 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_cistatic int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) 26608c2ecf20Sopenharmony_ci{ 26618c2ecf20Sopenharmony_ci struct smp_cmd_sign_info *rp = (void *) skb->data; 26628c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 26638c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 26648c2ecf20Sopenharmony_ci struct smp_csrk *csrk; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "conn %p", conn); 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rp)) 26698c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci /* Mark the information as received */ 26728c2ecf20Sopenharmony_ci smp->remote_key_dist &= ~SMP_DIST_SIGN; 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*rp)); 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); 26778c2ecf20Sopenharmony_ci if (csrk) { 26788c2ecf20Sopenharmony_ci if (conn->hcon->sec_level > BT_SECURITY_MEDIUM) 26798c2ecf20Sopenharmony_ci csrk->type = MGMT_CSRK_REMOTE_AUTHENTICATED; 26808c2ecf20Sopenharmony_ci else 26818c2ecf20Sopenharmony_ci csrk->type = MGMT_CSRK_REMOTE_UNAUTHENTICATED; 26828c2ecf20Sopenharmony_ci memcpy(csrk->val, rp->csrk, sizeof(csrk->val)); 26838c2ecf20Sopenharmony_ci } 26848c2ecf20Sopenharmony_ci smp->csrk = csrk; 26858c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci return 0; 26888c2ecf20Sopenharmony_ci} 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_cistatic u8 sc_select_method(struct smp_chan *smp) 26918c2ecf20Sopenharmony_ci{ 26928c2ecf20Sopenharmony_ci struct l2cap_conn *conn = smp->conn; 26938c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 26948c2ecf20Sopenharmony_ci struct smp_cmd_pairing *local, *remote; 26958c2ecf20Sopenharmony_ci u8 local_mitm, remote_mitm, local_io, remote_io, method; 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags) || 26988c2ecf20Sopenharmony_ci test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) 26998c2ecf20Sopenharmony_ci return REQ_OOB; 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci /* The preq/prsp contain the raw Pairing Request/Response PDUs 27028c2ecf20Sopenharmony_ci * which are needed as inputs to some crypto functions. To get 27038c2ecf20Sopenharmony_ci * the "struct smp_cmd_pairing" from them we need to skip the 27048c2ecf20Sopenharmony_ci * first byte which contains the opcode. 27058c2ecf20Sopenharmony_ci */ 27068c2ecf20Sopenharmony_ci if (hcon->out) { 27078c2ecf20Sopenharmony_ci local = (void *) &smp->preq[1]; 27088c2ecf20Sopenharmony_ci remote = (void *) &smp->prsp[1]; 27098c2ecf20Sopenharmony_ci } else { 27108c2ecf20Sopenharmony_ci local = (void *) &smp->prsp[1]; 27118c2ecf20Sopenharmony_ci remote = (void *) &smp->preq[1]; 27128c2ecf20Sopenharmony_ci } 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci local_io = local->io_capability; 27158c2ecf20Sopenharmony_ci remote_io = remote->io_capability; 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci local_mitm = (local->auth_req & SMP_AUTH_MITM); 27188c2ecf20Sopenharmony_ci remote_mitm = (remote->auth_req & SMP_AUTH_MITM); 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci /* If either side wants MITM, look up the method from the table, 27218c2ecf20Sopenharmony_ci * otherwise use JUST WORKS. 27228c2ecf20Sopenharmony_ci */ 27238c2ecf20Sopenharmony_ci if (local_mitm || remote_mitm) 27248c2ecf20Sopenharmony_ci method = get_auth_method(smp, local_io, remote_io); 27258c2ecf20Sopenharmony_ci else 27268c2ecf20Sopenharmony_ci method = JUST_WORKS; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci /* Don't confirm locally initiated pairing attempts */ 27298c2ecf20Sopenharmony_ci if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) 27308c2ecf20Sopenharmony_ci method = JUST_WORKS; 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci return method; 27338c2ecf20Sopenharmony_ci} 27348c2ecf20Sopenharmony_ci 27358c2ecf20Sopenharmony_cistatic int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) 27368c2ecf20Sopenharmony_ci{ 27378c2ecf20Sopenharmony_ci struct smp_cmd_public_key *key = (void *) skb->data; 27388c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 27398c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 27408c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 27418c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 27428c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh; 27438c2ecf20Sopenharmony_ci struct smp_cmd_pairing_confirm cfm; 27448c2ecf20Sopenharmony_ci int err; 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "conn %p", conn); 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci if (skb->len < sizeof(*key)) 27498c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci /* Check if remote and local public keys are the same and debug key is 27528c2ecf20Sopenharmony_ci * not in use. 27538c2ecf20Sopenharmony_ci */ 27548c2ecf20Sopenharmony_ci if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && 27558c2ecf20Sopenharmony_ci !crypto_memneq(key, smp->local_pk, 64)) { 27568c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Remote and local public keys are identical"); 27578c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 27588c2ecf20Sopenharmony_ci } 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci memcpy(smp->remote_pk, key, 64); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags)) { 27638c2ecf20Sopenharmony_ci err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk, 27648c2ecf20Sopenharmony_ci smp->rr, 0, cfm.confirm_val); 27658c2ecf20Sopenharmony_ci if (err) 27668c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) 27698c2ecf20Sopenharmony_ci return SMP_CONFIRM_FAILED; 27708c2ecf20Sopenharmony_ci } 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci /* Non-initiating device sends its public key after receiving 27738c2ecf20Sopenharmony_ci * the key from the initiating device. 27748c2ecf20Sopenharmony_ci */ 27758c2ecf20Sopenharmony_ci if (!hcon->out) { 27768c2ecf20Sopenharmony_ci err = sc_send_public_key(smp); 27778c2ecf20Sopenharmony_ci if (err) 27788c2ecf20Sopenharmony_ci return err; 27798c2ecf20Sopenharmony_ci } 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk); 27828c2ecf20Sopenharmony_ci SMP_DBG("Remote Public Key Y: %32phN", smp->remote_pk + 32); 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci /* Compute the shared secret on the same crypto tfm on which the private 27858c2ecf20Sopenharmony_ci * key was set/generated. 27868c2ecf20Sopenharmony_ci */ 27878c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) { 27888c2ecf20Sopenharmony_ci struct l2cap_chan *hchan = hdev->smp_data; 27898c2ecf20Sopenharmony_ci struct smp_dev *smp_dev; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci if (!hchan || !hchan->data) 27928c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci smp_dev = hchan->data; 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci tfm_ecdh = smp_dev->tfm_ecdh; 27978c2ecf20Sopenharmony_ci } else { 27988c2ecf20Sopenharmony_ci tfm_ecdh = smp->tfm_ecdh; 27998c2ecf20Sopenharmony_ci } 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci if (compute_ecdh_secret(tfm_ecdh, smp->remote_pk, smp->dhkey)) 28028c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci SMP_DBG("DHKey %32phN", smp->dhkey); 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_REMOTE_PK, &smp->flags); 28078c2ecf20Sopenharmony_ci 28088c2ecf20Sopenharmony_ci smp->method = sc_select_method(smp); 28098c2ecf20Sopenharmony_ci 28108c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "selected method 0x%02x", smp->method); 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci /* JUST_WORKS and JUST_CFM result in an unauthenticated key */ 28138c2ecf20Sopenharmony_ci if (smp->method == JUST_WORKS || smp->method == JUST_CFM) 28148c2ecf20Sopenharmony_ci hcon->pending_sec_level = BT_SECURITY_MEDIUM; 28158c2ecf20Sopenharmony_ci else 28168c2ecf20Sopenharmony_ci hcon->pending_sec_level = BT_SECURITY_FIPS; 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) 28198c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci if (smp->method == DSP_PASSKEY) { 28228c2ecf20Sopenharmony_ci get_random_bytes(&hcon->passkey_notify, 28238c2ecf20Sopenharmony_ci sizeof(hcon->passkey_notify)); 28248c2ecf20Sopenharmony_ci hcon->passkey_notify %= 1000000; 28258c2ecf20Sopenharmony_ci hcon->passkey_entered = 0; 28268c2ecf20Sopenharmony_ci smp->passkey_round = 0; 28278c2ecf20Sopenharmony_ci if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type, 28288c2ecf20Sopenharmony_ci hcon->dst_type, 28298c2ecf20Sopenharmony_ci hcon->passkey_notify, 28308c2ecf20Sopenharmony_ci hcon->passkey_entered)) 28318c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 28328c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 28338c2ecf20Sopenharmony_ci return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY); 28348c2ecf20Sopenharmony_ci } 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci if (smp->method == REQ_OOB) { 28378c2ecf20Sopenharmony_ci if (hcon->out) 28388c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 28398c2ecf20Sopenharmony_ci sizeof(smp->prnd), smp->prnd); 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci return 0; 28448c2ecf20Sopenharmony_ci } 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_ci if (hcon->out) 28478c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY) { 28508c2ecf20Sopenharmony_ci if (mgmt_user_passkey_request(hdev, &hcon->dst, hcon->type, 28518c2ecf20Sopenharmony_ci hcon->dst_type)) 28528c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 28538c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); 28548c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_WAIT_USER, &smp->flags); 28558c2ecf20Sopenharmony_ci return 0; 28568c2ecf20Sopenharmony_ci } 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_ci /* The Initiating device waits for the non-initiating device to 28598c2ecf20Sopenharmony_ci * send the confirm value. 28608c2ecf20Sopenharmony_ci */ 28618c2ecf20Sopenharmony_ci if (conn->hcon->out) 28628c2ecf20Sopenharmony_ci return 0; 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_ci err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, 28658c2ecf20Sopenharmony_ci 0, cfm.confirm_val); 28668c2ecf20Sopenharmony_ci if (err) 28678c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm); 28708c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci return 0; 28738c2ecf20Sopenharmony_ci} 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_cistatic int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) 28768c2ecf20Sopenharmony_ci{ 28778c2ecf20Sopenharmony_ci struct smp_cmd_dhkey_check *check = (void *) skb->data; 28788c2ecf20Sopenharmony_ci struct l2cap_chan *chan = conn->smp; 28798c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 28808c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 28818c2ecf20Sopenharmony_ci u8 a[7], b[7], *local_addr, *remote_addr; 28828c2ecf20Sopenharmony_ci u8 io_cap[3], r[16], e[16]; 28838c2ecf20Sopenharmony_ci int err; 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "conn %p", conn); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci if (skb->len < sizeof(*check)) 28888c2ecf20Sopenharmony_ci return SMP_INVALID_PARAMS; 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci memcpy(a, &hcon->init_addr, 6); 28918c2ecf20Sopenharmony_ci memcpy(b, &hcon->resp_addr, 6); 28928c2ecf20Sopenharmony_ci a[6] = hcon->init_addr_type; 28938c2ecf20Sopenharmony_ci b[6] = hcon->resp_addr_type; 28948c2ecf20Sopenharmony_ci 28958c2ecf20Sopenharmony_ci if (hcon->out) { 28968c2ecf20Sopenharmony_ci local_addr = a; 28978c2ecf20Sopenharmony_ci remote_addr = b; 28988c2ecf20Sopenharmony_ci memcpy(io_cap, &smp->prsp[1], 3); 28998c2ecf20Sopenharmony_ci } else { 29008c2ecf20Sopenharmony_ci local_addr = b; 29018c2ecf20Sopenharmony_ci remote_addr = a; 29028c2ecf20Sopenharmony_ci memcpy(io_cap, &smp->preq[1], 3); 29038c2ecf20Sopenharmony_ci } 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci memset(r, 0, sizeof(r)); 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ci if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) 29088c2ecf20Sopenharmony_ci put_unaligned_le32(hcon->passkey_notify, r); 29098c2ecf20Sopenharmony_ci else if (smp->method == REQ_OOB) 29108c2ecf20Sopenharmony_ci memcpy(r, smp->lr, 16); 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r, 29138c2ecf20Sopenharmony_ci io_cap, remote_addr, local_addr, e); 29148c2ecf20Sopenharmony_ci if (err) 29158c2ecf20Sopenharmony_ci return SMP_UNSPECIFIED; 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci if (crypto_memneq(check->e, e, 16)) 29188c2ecf20Sopenharmony_ci return SMP_DHKEY_CHECK_FAILED; 29198c2ecf20Sopenharmony_ci 29208c2ecf20Sopenharmony_ci if (!hcon->out) { 29218c2ecf20Sopenharmony_ci if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) { 29228c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags); 29238c2ecf20Sopenharmony_ci return 0; 29248c2ecf20Sopenharmony_ci } 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci /* Responder sends DHKey check as response to initiator */ 29278c2ecf20Sopenharmony_ci sc_dhkey_check(smp); 29288c2ecf20Sopenharmony_ci } 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci sc_add_ltk(smp); 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci if (hcon->out) { 29338c2ecf20Sopenharmony_ci hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size); 29348c2ecf20Sopenharmony_ci hcon->enc_key_size = smp->enc_key_size; 29358c2ecf20Sopenharmony_ci } 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci return 0; 29388c2ecf20Sopenharmony_ci} 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_cistatic int smp_cmd_keypress_notify(struct l2cap_conn *conn, 29418c2ecf20Sopenharmony_ci struct sk_buff *skb) 29428c2ecf20Sopenharmony_ci{ 29438c2ecf20Sopenharmony_ci struct smp_cmd_keypress_notify *kp = (void *) skb->data; 29448c2ecf20Sopenharmony_ci 29458c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "value 0x%02x", kp->value); 29468c2ecf20Sopenharmony_ci 29478c2ecf20Sopenharmony_ci return 0; 29488c2ecf20Sopenharmony_ci} 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_cistatic int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) 29518c2ecf20Sopenharmony_ci{ 29528c2ecf20Sopenharmony_ci struct l2cap_conn *conn = chan->conn; 29538c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 29548c2ecf20Sopenharmony_ci struct smp_chan *smp; 29558c2ecf20Sopenharmony_ci __u8 code, reason; 29568c2ecf20Sopenharmony_ci int err = 0; 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci if (skb->len < 1) 29598c2ecf20Sopenharmony_ci return -EILSEQ; 29608c2ecf20Sopenharmony_ci 29618c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) { 29628c2ecf20Sopenharmony_ci reason = SMP_PAIRING_NOTSUPP; 29638c2ecf20Sopenharmony_ci goto done; 29648c2ecf20Sopenharmony_ci } 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_ci code = skb->data[0]; 29678c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(code)); 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci smp = chan->data; 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci if (code > SMP_CMD_MAX) 29728c2ecf20Sopenharmony_ci goto drop; 29738c2ecf20Sopenharmony_ci 29748c2ecf20Sopenharmony_ci if (smp && !test_and_clear_bit(code, &smp->allow_cmd)) 29758c2ecf20Sopenharmony_ci goto drop; 29768c2ecf20Sopenharmony_ci 29778c2ecf20Sopenharmony_ci /* If we don't have a context the only allowed commands are 29788c2ecf20Sopenharmony_ci * pairing request and security request. 29798c2ecf20Sopenharmony_ci */ 29808c2ecf20Sopenharmony_ci if (!smp && code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ) 29818c2ecf20Sopenharmony_ci goto drop; 29828c2ecf20Sopenharmony_ci 29838c2ecf20Sopenharmony_ci switch (code) { 29848c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_REQ: 29858c2ecf20Sopenharmony_ci reason = smp_cmd_pairing_req(conn, skb); 29868c2ecf20Sopenharmony_ci break; 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_FAIL: 29898c2ecf20Sopenharmony_ci smp_failure(conn, 0); 29908c2ecf20Sopenharmony_ci err = -EPERM; 29918c2ecf20Sopenharmony_ci break; 29928c2ecf20Sopenharmony_ci 29938c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_RSP: 29948c2ecf20Sopenharmony_ci reason = smp_cmd_pairing_rsp(conn, skb); 29958c2ecf20Sopenharmony_ci break; 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_ci case SMP_CMD_SECURITY_REQ: 29988c2ecf20Sopenharmony_ci reason = smp_cmd_security_req(conn, skb); 29998c2ecf20Sopenharmony_ci break; 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_CONFIRM: 30028c2ecf20Sopenharmony_ci reason = smp_cmd_pairing_confirm(conn, skb); 30038c2ecf20Sopenharmony_ci break; 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci case SMP_CMD_PAIRING_RANDOM: 30068c2ecf20Sopenharmony_ci reason = smp_cmd_pairing_random(conn, skb); 30078c2ecf20Sopenharmony_ci break; 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci case SMP_CMD_ENCRYPT_INFO: 30108c2ecf20Sopenharmony_ci reason = smp_cmd_encrypt_info(conn, skb); 30118c2ecf20Sopenharmony_ci break; 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ci case SMP_CMD_INITIATOR_IDENT: 30148c2ecf20Sopenharmony_ci reason = smp_cmd_initiator_ident(conn, skb); 30158c2ecf20Sopenharmony_ci break; 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_ci case SMP_CMD_IDENT_INFO: 30188c2ecf20Sopenharmony_ci reason = smp_cmd_ident_info(conn, skb); 30198c2ecf20Sopenharmony_ci break; 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci case SMP_CMD_IDENT_ADDR_INFO: 30228c2ecf20Sopenharmony_ci reason = smp_cmd_ident_addr_info(conn, skb); 30238c2ecf20Sopenharmony_ci break; 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_ci case SMP_CMD_SIGN_INFO: 30268c2ecf20Sopenharmony_ci reason = smp_cmd_sign_info(conn, skb); 30278c2ecf20Sopenharmony_ci break; 30288c2ecf20Sopenharmony_ci 30298c2ecf20Sopenharmony_ci case SMP_CMD_PUBLIC_KEY: 30308c2ecf20Sopenharmony_ci reason = smp_cmd_public_key(conn, skb); 30318c2ecf20Sopenharmony_ci break; 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci case SMP_CMD_DHKEY_CHECK: 30348c2ecf20Sopenharmony_ci reason = smp_cmd_dhkey_check(conn, skb); 30358c2ecf20Sopenharmony_ci break; 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci case SMP_CMD_KEYPRESS_NOTIFY: 30388c2ecf20Sopenharmony_ci reason = smp_cmd_keypress_notify(conn, skb); 30398c2ecf20Sopenharmony_ci break; 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_ci default: 30428c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "Unknown command code 0x%2.2x", code); 30438c2ecf20Sopenharmony_ci reason = SMP_CMD_NOTSUPP; 30448c2ecf20Sopenharmony_ci goto done; 30458c2ecf20Sopenharmony_ci } 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_cidone: 30488c2ecf20Sopenharmony_ci if (!err) { 30498c2ecf20Sopenharmony_ci if (reason) 30508c2ecf20Sopenharmony_ci smp_failure(conn, reason); 30518c2ecf20Sopenharmony_ci kfree_skb(skb); 30528c2ecf20Sopenharmony_ci } 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci return err; 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_cidrop: 30578c2ecf20Sopenharmony_ci bt_dev_err(hcon->hdev, "unexpected SMP command 0x%02x from %pMR", 30588c2ecf20Sopenharmony_ci code, &hcon->dst); 30598c2ecf20Sopenharmony_ci kfree_skb(skb); 30608c2ecf20Sopenharmony_ci return 0; 30618c2ecf20Sopenharmony_ci} 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_cistatic void smp_teardown_cb(struct l2cap_chan *chan, int err) 30648c2ecf20Sopenharmony_ci{ 30658c2ecf20Sopenharmony_ci struct l2cap_conn *conn = chan->conn; 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci bt_dev_dbg(conn->hcon->hdev, "chan %p", chan); 30688c2ecf20Sopenharmony_ci 30698c2ecf20Sopenharmony_ci if (chan->data) 30708c2ecf20Sopenharmony_ci smp_chan_destroy(conn); 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_ci conn->smp = NULL; 30738c2ecf20Sopenharmony_ci l2cap_chan_put(chan); 30748c2ecf20Sopenharmony_ci} 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_cistatic void bredr_pairing(struct l2cap_chan *chan) 30778c2ecf20Sopenharmony_ci{ 30788c2ecf20Sopenharmony_ci struct l2cap_conn *conn = chan->conn; 30798c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 30808c2ecf20Sopenharmony_ci struct hci_dev *hdev = hcon->hdev; 30818c2ecf20Sopenharmony_ci struct smp_cmd_pairing req; 30828c2ecf20Sopenharmony_ci struct smp_chan *smp; 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "chan %p", chan); 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci /* Only new pairings are interesting */ 30878c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags)) 30888c2ecf20Sopenharmony_ci return; 30898c2ecf20Sopenharmony_ci 30908c2ecf20Sopenharmony_ci /* Don't bother if we're not encrypted */ 30918c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags)) 30928c2ecf20Sopenharmony_ci return; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci /* Only initiator may initiate SMP over BR/EDR */ 30958c2ecf20Sopenharmony_ci if (hcon->role != HCI_ROLE_MASTER) 30968c2ecf20Sopenharmony_ci return; 30978c2ecf20Sopenharmony_ci 30988c2ecf20Sopenharmony_ci /* Secure Connections support must be enabled */ 30998c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SC_ENABLED)) 31008c2ecf20Sopenharmony_ci return; 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci /* BR/EDR must use Secure Connections for SMP */ 31038c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) && 31048c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) 31058c2ecf20Sopenharmony_ci return; 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_ci /* If our LE support is not enabled don't do anything */ 31088c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 31098c2ecf20Sopenharmony_ci return; 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci /* Don't bother if remote LE support is not enabled */ 31128c2ecf20Sopenharmony_ci if (!lmp_host_le_capable(hcon)) 31138c2ecf20Sopenharmony_ci return; 31148c2ecf20Sopenharmony_ci 31158c2ecf20Sopenharmony_ci /* Remote must support SMP fixed chan for BR/EDR */ 31168c2ecf20Sopenharmony_ci if (!(conn->remote_fixed_chan & L2CAP_FC_SMP_BREDR)) 31178c2ecf20Sopenharmony_ci return; 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_ci /* Don't bother if SMP is already ongoing */ 31208c2ecf20Sopenharmony_ci if (chan->data) 31218c2ecf20Sopenharmony_ci return; 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci smp = smp_chan_create(conn); 31248c2ecf20Sopenharmony_ci if (!smp) { 31258c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unable to create SMP context for BR/EDR"); 31268c2ecf20Sopenharmony_ci return; 31278c2ecf20Sopenharmony_ci } 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci set_bit(SMP_FLAG_SC, &smp->flags); 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "starting SMP over BR/EDR"); 31328c2ecf20Sopenharmony_ci 31338c2ecf20Sopenharmony_ci /* Prepare and send the BR/EDR SMP Pairing Request */ 31348c2ecf20Sopenharmony_ci build_bredr_pairing_cmd(smp, &req, NULL); 31358c2ecf20Sopenharmony_ci 31368c2ecf20Sopenharmony_ci smp->preq[0] = SMP_CMD_PAIRING_REQ; 31378c2ecf20Sopenharmony_ci memcpy(&smp->preq[1], &req, sizeof(req)); 31388c2ecf20Sopenharmony_ci 31398c2ecf20Sopenharmony_ci smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req); 31408c2ecf20Sopenharmony_ci SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); 31418c2ecf20Sopenharmony_ci} 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_cistatic void smp_resume_cb(struct l2cap_chan *chan) 31448c2ecf20Sopenharmony_ci{ 31458c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 31468c2ecf20Sopenharmony_ci struct l2cap_conn *conn = chan->conn; 31478c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 31488c2ecf20Sopenharmony_ci 31498c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "chan %p", chan); 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci if (hcon->type == ACL_LINK) { 31528c2ecf20Sopenharmony_ci bredr_pairing(chan); 31538c2ecf20Sopenharmony_ci return; 31548c2ecf20Sopenharmony_ci } 31558c2ecf20Sopenharmony_ci 31568c2ecf20Sopenharmony_ci if (!smp) 31578c2ecf20Sopenharmony_ci return; 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags)) 31608c2ecf20Sopenharmony_ci return; 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci cancel_delayed_work(&smp->security_timer); 31638c2ecf20Sopenharmony_ci 31648c2ecf20Sopenharmony_ci smp_distribute_keys(smp); 31658c2ecf20Sopenharmony_ci} 31668c2ecf20Sopenharmony_ci 31678c2ecf20Sopenharmony_cistatic void smp_ready_cb(struct l2cap_chan *chan) 31688c2ecf20Sopenharmony_ci{ 31698c2ecf20Sopenharmony_ci struct l2cap_conn *conn = chan->conn; 31708c2ecf20Sopenharmony_ci struct hci_conn *hcon = conn->hcon; 31718c2ecf20Sopenharmony_ci 31728c2ecf20Sopenharmony_ci bt_dev_dbg(hcon->hdev, "chan %p", chan); 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ci /* No need to call l2cap_chan_hold() here since we already own 31758c2ecf20Sopenharmony_ci * the reference taken in smp_new_conn_cb(). This is just the 31768c2ecf20Sopenharmony_ci * first time that we tie it to a specific pointer. The code in 31778c2ecf20Sopenharmony_ci * l2cap_core.c ensures that there's no risk this function wont 31788c2ecf20Sopenharmony_ci * get called if smp_new_conn_cb was previously called. 31798c2ecf20Sopenharmony_ci */ 31808c2ecf20Sopenharmony_ci conn->smp = chan; 31818c2ecf20Sopenharmony_ci 31828c2ecf20Sopenharmony_ci if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags)) 31838c2ecf20Sopenharmony_ci bredr_pairing(chan); 31848c2ecf20Sopenharmony_ci} 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_cistatic int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) 31878c2ecf20Sopenharmony_ci{ 31888c2ecf20Sopenharmony_ci int err; 31898c2ecf20Sopenharmony_ci 31908c2ecf20Sopenharmony_ci bt_dev_dbg(chan->conn->hcon->hdev, "chan %p", chan); 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci err = smp_sig_channel(chan, skb); 31938c2ecf20Sopenharmony_ci if (err) { 31948c2ecf20Sopenharmony_ci struct smp_chan *smp = chan->data; 31958c2ecf20Sopenharmony_ci 31968c2ecf20Sopenharmony_ci if (smp) 31978c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&smp->security_timer); 31988c2ecf20Sopenharmony_ci 31998c2ecf20Sopenharmony_ci hci_disconnect(chan->conn->hcon, HCI_ERROR_AUTH_FAILURE); 32008c2ecf20Sopenharmony_ci } 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci return err; 32038c2ecf20Sopenharmony_ci} 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_cistatic struct sk_buff *smp_alloc_skb_cb(struct l2cap_chan *chan, 32068c2ecf20Sopenharmony_ci unsigned long hdr_len, 32078c2ecf20Sopenharmony_ci unsigned long len, int nb) 32088c2ecf20Sopenharmony_ci{ 32098c2ecf20Sopenharmony_ci struct sk_buff *skb; 32108c2ecf20Sopenharmony_ci 32118c2ecf20Sopenharmony_ci skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL); 32128c2ecf20Sopenharmony_ci if (!skb) 32138c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci skb->priority = HCI_PRIO_MAX; 32168c2ecf20Sopenharmony_ci bt_cb(skb)->l2cap.chan = chan; 32178c2ecf20Sopenharmony_ci 32188c2ecf20Sopenharmony_ci return skb; 32198c2ecf20Sopenharmony_ci} 32208c2ecf20Sopenharmony_ci 32218c2ecf20Sopenharmony_cistatic const struct l2cap_ops smp_chan_ops = { 32228c2ecf20Sopenharmony_ci .name = "Security Manager", 32238c2ecf20Sopenharmony_ci .ready = smp_ready_cb, 32248c2ecf20Sopenharmony_ci .recv = smp_recv_cb, 32258c2ecf20Sopenharmony_ci .alloc_skb = smp_alloc_skb_cb, 32268c2ecf20Sopenharmony_ci .teardown = smp_teardown_cb, 32278c2ecf20Sopenharmony_ci .resume = smp_resume_cb, 32288c2ecf20Sopenharmony_ci 32298c2ecf20Sopenharmony_ci .new_connection = l2cap_chan_no_new_connection, 32308c2ecf20Sopenharmony_ci .state_change = l2cap_chan_no_state_change, 32318c2ecf20Sopenharmony_ci .close = l2cap_chan_no_close, 32328c2ecf20Sopenharmony_ci .defer = l2cap_chan_no_defer, 32338c2ecf20Sopenharmony_ci .suspend = l2cap_chan_no_suspend, 32348c2ecf20Sopenharmony_ci .set_shutdown = l2cap_chan_no_set_shutdown, 32358c2ecf20Sopenharmony_ci .get_sndtimeo = l2cap_chan_no_get_sndtimeo, 32368c2ecf20Sopenharmony_ci}; 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_cistatic inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) 32398c2ecf20Sopenharmony_ci{ 32408c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci BT_DBG("pchan %p", pchan); 32438c2ecf20Sopenharmony_ci 32448c2ecf20Sopenharmony_ci chan = l2cap_chan_create(); 32458c2ecf20Sopenharmony_ci if (!chan) 32468c2ecf20Sopenharmony_ci return NULL; 32478c2ecf20Sopenharmony_ci 32488c2ecf20Sopenharmony_ci chan->chan_type = pchan->chan_type; 32498c2ecf20Sopenharmony_ci chan->ops = &smp_chan_ops; 32508c2ecf20Sopenharmony_ci chan->scid = pchan->scid; 32518c2ecf20Sopenharmony_ci chan->dcid = chan->scid; 32528c2ecf20Sopenharmony_ci chan->imtu = pchan->imtu; 32538c2ecf20Sopenharmony_ci chan->omtu = pchan->omtu; 32548c2ecf20Sopenharmony_ci chan->mode = pchan->mode; 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci /* Other L2CAP channels may request SMP routines in order to 32578c2ecf20Sopenharmony_ci * change the security level. This means that the SMP channel 32588c2ecf20Sopenharmony_ci * lock must be considered in its own category to avoid lockdep 32598c2ecf20Sopenharmony_ci * warnings. 32608c2ecf20Sopenharmony_ci */ 32618c2ecf20Sopenharmony_ci atomic_set(&chan->nesting, L2CAP_NESTING_SMP); 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci BT_DBG("created chan %p", chan); 32648c2ecf20Sopenharmony_ci 32658c2ecf20Sopenharmony_ci return chan; 32668c2ecf20Sopenharmony_ci} 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_cistatic const struct l2cap_ops smp_root_chan_ops = { 32698c2ecf20Sopenharmony_ci .name = "Security Manager Root", 32708c2ecf20Sopenharmony_ci .new_connection = smp_new_conn_cb, 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci /* None of these are implemented for the root channel */ 32738c2ecf20Sopenharmony_ci .close = l2cap_chan_no_close, 32748c2ecf20Sopenharmony_ci .alloc_skb = l2cap_chan_no_alloc_skb, 32758c2ecf20Sopenharmony_ci .recv = l2cap_chan_no_recv, 32768c2ecf20Sopenharmony_ci .state_change = l2cap_chan_no_state_change, 32778c2ecf20Sopenharmony_ci .teardown = l2cap_chan_no_teardown, 32788c2ecf20Sopenharmony_ci .ready = l2cap_chan_no_ready, 32798c2ecf20Sopenharmony_ci .defer = l2cap_chan_no_defer, 32808c2ecf20Sopenharmony_ci .suspend = l2cap_chan_no_suspend, 32818c2ecf20Sopenharmony_ci .resume = l2cap_chan_no_resume, 32828c2ecf20Sopenharmony_ci .set_shutdown = l2cap_chan_no_set_shutdown, 32838c2ecf20Sopenharmony_ci .get_sndtimeo = l2cap_chan_no_get_sndtimeo, 32848c2ecf20Sopenharmony_ci}; 32858c2ecf20Sopenharmony_ci 32868c2ecf20Sopenharmony_cistatic struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) 32878c2ecf20Sopenharmony_ci{ 32888c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 32898c2ecf20Sopenharmony_ci struct smp_dev *smp; 32908c2ecf20Sopenharmony_ci struct crypto_shash *tfm_cmac; 32918c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh; 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci if (cid == L2CAP_CID_SMP_BREDR) { 32948c2ecf20Sopenharmony_ci smp = NULL; 32958c2ecf20Sopenharmony_ci goto create_chan; 32968c2ecf20Sopenharmony_ci } 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci smp = kzalloc(sizeof(*smp), GFP_KERNEL); 32998c2ecf20Sopenharmony_ci if (!smp) 33008c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 33018c2ecf20Sopenharmony_ci 33028c2ecf20Sopenharmony_ci tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); 33038c2ecf20Sopenharmony_ci if (IS_ERR(tfm_cmac)) { 33048c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Unable to create CMAC crypto context"); 33058c2ecf20Sopenharmony_ci kfree_sensitive(smp); 33068c2ecf20Sopenharmony_ci return ERR_CAST(tfm_cmac); 33078c2ecf20Sopenharmony_ci } 33088c2ecf20Sopenharmony_ci 33098c2ecf20Sopenharmony_ci tfm_ecdh = crypto_alloc_kpp("ecdh", 0, 0); 33108c2ecf20Sopenharmony_ci if (IS_ERR(tfm_ecdh)) { 33118c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Unable to create ECDH crypto context"); 33128c2ecf20Sopenharmony_ci crypto_free_shash(tfm_cmac); 33138c2ecf20Sopenharmony_ci kfree_sensitive(smp); 33148c2ecf20Sopenharmony_ci return ERR_CAST(tfm_ecdh); 33158c2ecf20Sopenharmony_ci } 33168c2ecf20Sopenharmony_ci 33178c2ecf20Sopenharmony_ci smp->local_oob = false; 33188c2ecf20Sopenharmony_ci smp->tfm_cmac = tfm_cmac; 33198c2ecf20Sopenharmony_ci smp->tfm_ecdh = tfm_ecdh; 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_cicreate_chan: 33228c2ecf20Sopenharmony_ci chan = l2cap_chan_create(); 33238c2ecf20Sopenharmony_ci if (!chan) { 33248c2ecf20Sopenharmony_ci if (smp) { 33258c2ecf20Sopenharmony_ci crypto_free_shash(smp->tfm_cmac); 33268c2ecf20Sopenharmony_ci crypto_free_kpp(smp->tfm_ecdh); 33278c2ecf20Sopenharmony_ci kfree_sensitive(smp); 33288c2ecf20Sopenharmony_ci } 33298c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 33308c2ecf20Sopenharmony_ci } 33318c2ecf20Sopenharmony_ci 33328c2ecf20Sopenharmony_ci chan->data = smp; 33338c2ecf20Sopenharmony_ci 33348c2ecf20Sopenharmony_ci l2cap_add_scid(chan, cid); 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci l2cap_chan_set_defaults(chan); 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci if (cid == L2CAP_CID_SMP) { 33398c2ecf20Sopenharmony_ci u8 bdaddr_type; 33408c2ecf20Sopenharmony_ci 33418c2ecf20Sopenharmony_ci hci_copy_identity_address(hdev, &chan->src, &bdaddr_type); 33428c2ecf20Sopenharmony_ci 33438c2ecf20Sopenharmony_ci if (bdaddr_type == ADDR_LE_DEV_PUBLIC) 33448c2ecf20Sopenharmony_ci chan->src_type = BDADDR_LE_PUBLIC; 33458c2ecf20Sopenharmony_ci else 33468c2ecf20Sopenharmony_ci chan->src_type = BDADDR_LE_RANDOM; 33478c2ecf20Sopenharmony_ci } else { 33488c2ecf20Sopenharmony_ci bacpy(&chan->src, &hdev->bdaddr); 33498c2ecf20Sopenharmony_ci chan->src_type = BDADDR_BREDR; 33508c2ecf20Sopenharmony_ci } 33518c2ecf20Sopenharmony_ci 33528c2ecf20Sopenharmony_ci chan->state = BT_LISTEN; 33538c2ecf20Sopenharmony_ci chan->mode = L2CAP_MODE_BASIC; 33548c2ecf20Sopenharmony_ci chan->imtu = L2CAP_DEFAULT_MTU; 33558c2ecf20Sopenharmony_ci chan->ops = &smp_root_chan_ops; 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci /* Set correct nesting level for a parent/listening channel */ 33588c2ecf20Sopenharmony_ci atomic_set(&chan->nesting, L2CAP_NESTING_PARENT); 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ci return chan; 33618c2ecf20Sopenharmony_ci} 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_cistatic void smp_del_chan(struct l2cap_chan *chan) 33648c2ecf20Sopenharmony_ci{ 33658c2ecf20Sopenharmony_ci struct smp_dev *smp; 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ci BT_DBG("chan %p", chan); 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci smp = chan->data; 33708c2ecf20Sopenharmony_ci if (smp) { 33718c2ecf20Sopenharmony_ci chan->data = NULL; 33728c2ecf20Sopenharmony_ci crypto_free_shash(smp->tfm_cmac); 33738c2ecf20Sopenharmony_ci crypto_free_kpp(smp->tfm_ecdh); 33748c2ecf20Sopenharmony_ci kfree_sensitive(smp); 33758c2ecf20Sopenharmony_ci } 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci l2cap_chan_put(chan); 33788c2ecf20Sopenharmony_ci} 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_cistatic ssize_t force_bredr_smp_read(struct file *file, 33818c2ecf20Sopenharmony_ci char __user *user_buf, 33828c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 33838c2ecf20Sopenharmony_ci{ 33848c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 33858c2ecf20Sopenharmony_ci char buf[3]; 33868c2ecf20Sopenharmony_ci 33878c2ecf20Sopenharmony_ci buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP) ? 'Y': 'N'; 33888c2ecf20Sopenharmony_ci buf[1] = '\n'; 33898c2ecf20Sopenharmony_ci buf[2] = '\0'; 33908c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 33918c2ecf20Sopenharmony_ci} 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_cistatic ssize_t force_bredr_smp_write(struct file *file, 33948c2ecf20Sopenharmony_ci const char __user *user_buf, 33958c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 33968c2ecf20Sopenharmony_ci{ 33978c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 33988c2ecf20Sopenharmony_ci bool enable; 33998c2ecf20Sopenharmony_ci int err; 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci err = kstrtobool_from_user(user_buf, count, &enable); 34028c2ecf20Sopenharmony_ci if (err) 34038c2ecf20Sopenharmony_ci return err; 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci if (enable == hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) 34068c2ecf20Sopenharmony_ci return -EALREADY; 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci if (enable) { 34098c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR); 34128c2ecf20Sopenharmony_ci if (IS_ERR(chan)) 34138c2ecf20Sopenharmony_ci return PTR_ERR(chan); 34148c2ecf20Sopenharmony_ci 34158c2ecf20Sopenharmony_ci hdev->smp_bredr_data = chan; 34168c2ecf20Sopenharmony_ci } else { 34178c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 34188c2ecf20Sopenharmony_ci 34198c2ecf20Sopenharmony_ci chan = hdev->smp_bredr_data; 34208c2ecf20Sopenharmony_ci hdev->smp_bredr_data = NULL; 34218c2ecf20Sopenharmony_ci smp_del_chan(chan); 34228c2ecf20Sopenharmony_ci } 34238c2ecf20Sopenharmony_ci 34248c2ecf20Sopenharmony_ci hci_dev_change_flag(hdev, HCI_FORCE_BREDR_SMP); 34258c2ecf20Sopenharmony_ci 34268c2ecf20Sopenharmony_ci return count; 34278c2ecf20Sopenharmony_ci} 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_cistatic const struct file_operations force_bredr_smp_fops = { 34308c2ecf20Sopenharmony_ci .open = simple_open, 34318c2ecf20Sopenharmony_ci .read = force_bredr_smp_read, 34328c2ecf20Sopenharmony_ci .write = force_bredr_smp_write, 34338c2ecf20Sopenharmony_ci .llseek = default_llseek, 34348c2ecf20Sopenharmony_ci}; 34358c2ecf20Sopenharmony_ci 34368c2ecf20Sopenharmony_ciint smp_register(struct hci_dev *hdev) 34378c2ecf20Sopenharmony_ci{ 34388c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 34398c2ecf20Sopenharmony_ci 34408c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, ""); 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_ci /* If the controller does not support Low Energy operation, then 34438c2ecf20Sopenharmony_ci * there is also no need to register any SMP channel. 34448c2ecf20Sopenharmony_ci */ 34458c2ecf20Sopenharmony_ci if (!lmp_le_capable(hdev)) 34468c2ecf20Sopenharmony_ci return 0; 34478c2ecf20Sopenharmony_ci 34488c2ecf20Sopenharmony_ci if (WARN_ON(hdev->smp_data)) { 34498c2ecf20Sopenharmony_ci chan = hdev->smp_data; 34508c2ecf20Sopenharmony_ci hdev->smp_data = NULL; 34518c2ecf20Sopenharmony_ci smp_del_chan(chan); 34528c2ecf20Sopenharmony_ci } 34538c2ecf20Sopenharmony_ci 34548c2ecf20Sopenharmony_ci chan = smp_add_cid(hdev, L2CAP_CID_SMP); 34558c2ecf20Sopenharmony_ci if (IS_ERR(chan)) 34568c2ecf20Sopenharmony_ci return PTR_ERR(chan); 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci hdev->smp_data = chan; 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci /* If the controller does not support BR/EDR Secure Connections 34618c2ecf20Sopenharmony_ci * feature, then the BR/EDR SMP channel shall not be present. 34628c2ecf20Sopenharmony_ci * 34638c2ecf20Sopenharmony_ci * To test this with Bluetooth 4.0 controllers, create a debugfs 34648c2ecf20Sopenharmony_ci * switch that allows forcing BR/EDR SMP support and accepting 34658c2ecf20Sopenharmony_ci * cross-transport pairing on non-AES encrypted connections. 34668c2ecf20Sopenharmony_ci */ 34678c2ecf20Sopenharmony_ci if (!lmp_sc_capable(hdev)) { 34688c2ecf20Sopenharmony_ci debugfs_create_file("force_bredr_smp", 0644, hdev->debugfs, 34698c2ecf20Sopenharmony_ci hdev, &force_bredr_smp_fops); 34708c2ecf20Sopenharmony_ci 34718c2ecf20Sopenharmony_ci /* Flag can be already set here (due to power toggle) */ 34728c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) 34738c2ecf20Sopenharmony_ci return 0; 34748c2ecf20Sopenharmony_ci } 34758c2ecf20Sopenharmony_ci 34768c2ecf20Sopenharmony_ci if (WARN_ON(hdev->smp_bredr_data)) { 34778c2ecf20Sopenharmony_ci chan = hdev->smp_bredr_data; 34788c2ecf20Sopenharmony_ci hdev->smp_bredr_data = NULL; 34798c2ecf20Sopenharmony_ci smp_del_chan(chan); 34808c2ecf20Sopenharmony_ci } 34818c2ecf20Sopenharmony_ci 34828c2ecf20Sopenharmony_ci chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR); 34838c2ecf20Sopenharmony_ci if (IS_ERR(chan)) { 34848c2ecf20Sopenharmony_ci int err = PTR_ERR(chan); 34858c2ecf20Sopenharmony_ci chan = hdev->smp_data; 34868c2ecf20Sopenharmony_ci hdev->smp_data = NULL; 34878c2ecf20Sopenharmony_ci smp_del_chan(chan); 34888c2ecf20Sopenharmony_ci return err; 34898c2ecf20Sopenharmony_ci } 34908c2ecf20Sopenharmony_ci 34918c2ecf20Sopenharmony_ci hdev->smp_bredr_data = chan; 34928c2ecf20Sopenharmony_ci 34938c2ecf20Sopenharmony_ci return 0; 34948c2ecf20Sopenharmony_ci} 34958c2ecf20Sopenharmony_ci 34968c2ecf20Sopenharmony_civoid smp_unregister(struct hci_dev *hdev) 34978c2ecf20Sopenharmony_ci{ 34988c2ecf20Sopenharmony_ci struct l2cap_chan *chan; 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci if (hdev->smp_bredr_data) { 35018c2ecf20Sopenharmony_ci chan = hdev->smp_bredr_data; 35028c2ecf20Sopenharmony_ci hdev->smp_bredr_data = NULL; 35038c2ecf20Sopenharmony_ci smp_del_chan(chan); 35048c2ecf20Sopenharmony_ci } 35058c2ecf20Sopenharmony_ci 35068c2ecf20Sopenharmony_ci if (hdev->smp_data) { 35078c2ecf20Sopenharmony_ci chan = hdev->smp_data; 35088c2ecf20Sopenharmony_ci hdev->smp_data = NULL; 35098c2ecf20Sopenharmony_ci smp_del_chan(chan); 35108c2ecf20Sopenharmony_ci } 35118c2ecf20Sopenharmony_ci} 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_BT_SELFTEST_SMP) 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_cistatic int __init test_debug_key(struct crypto_kpp *tfm_ecdh) 35168c2ecf20Sopenharmony_ci{ 35178c2ecf20Sopenharmony_ci u8 pk[64]; 35188c2ecf20Sopenharmony_ci int err; 35198c2ecf20Sopenharmony_ci 35208c2ecf20Sopenharmony_ci err = set_ecdh_privkey(tfm_ecdh, debug_sk); 35218c2ecf20Sopenharmony_ci if (err) 35228c2ecf20Sopenharmony_ci return err; 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci err = generate_ecdh_public_key(tfm_ecdh, pk); 35258c2ecf20Sopenharmony_ci if (err) 35268c2ecf20Sopenharmony_ci return err; 35278c2ecf20Sopenharmony_ci 35288c2ecf20Sopenharmony_ci if (crypto_memneq(pk, debug_pk, 64)) 35298c2ecf20Sopenharmony_ci return -EINVAL; 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci return 0; 35328c2ecf20Sopenharmony_ci} 35338c2ecf20Sopenharmony_ci 35348c2ecf20Sopenharmony_cistatic int __init test_ah(void) 35358c2ecf20Sopenharmony_ci{ 35368c2ecf20Sopenharmony_ci const u8 irk[16] = { 35378c2ecf20Sopenharmony_ci 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, 35388c2ecf20Sopenharmony_ci 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec }; 35398c2ecf20Sopenharmony_ci const u8 r[3] = { 0x94, 0x81, 0x70 }; 35408c2ecf20Sopenharmony_ci const u8 exp[3] = { 0xaa, 0xfb, 0x0d }; 35418c2ecf20Sopenharmony_ci u8 res[3]; 35428c2ecf20Sopenharmony_ci int err; 35438c2ecf20Sopenharmony_ci 35448c2ecf20Sopenharmony_ci err = smp_ah(irk, r, res); 35458c2ecf20Sopenharmony_ci if (err) 35468c2ecf20Sopenharmony_ci return err; 35478c2ecf20Sopenharmony_ci 35488c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 3)) 35498c2ecf20Sopenharmony_ci return -EINVAL; 35508c2ecf20Sopenharmony_ci 35518c2ecf20Sopenharmony_ci return 0; 35528c2ecf20Sopenharmony_ci} 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_cistatic int __init test_c1(void) 35558c2ecf20Sopenharmony_ci{ 35568c2ecf20Sopenharmony_ci const u8 k[16] = { 35578c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35588c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 35598c2ecf20Sopenharmony_ci const u8 r[16] = { 35608c2ecf20Sopenharmony_ci 0xe0, 0x2e, 0x70, 0xc6, 0x4e, 0x27, 0x88, 0x63, 35618c2ecf20Sopenharmony_ci 0x0e, 0x6f, 0xad, 0x56, 0x21, 0xd5, 0x83, 0x57 }; 35628c2ecf20Sopenharmony_ci const u8 preq[7] = { 0x01, 0x01, 0x00, 0x00, 0x10, 0x07, 0x07 }; 35638c2ecf20Sopenharmony_ci const u8 pres[7] = { 0x02, 0x03, 0x00, 0x00, 0x08, 0x00, 0x05 }; 35648c2ecf20Sopenharmony_ci const u8 _iat = 0x01; 35658c2ecf20Sopenharmony_ci const u8 _rat = 0x00; 35668c2ecf20Sopenharmony_ci const bdaddr_t ra = { { 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1 } }; 35678c2ecf20Sopenharmony_ci const bdaddr_t ia = { { 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1 } }; 35688c2ecf20Sopenharmony_ci const u8 exp[16] = { 35698c2ecf20Sopenharmony_ci 0x86, 0x3b, 0xf1, 0xbe, 0xc5, 0x4d, 0xa7, 0xd2, 35708c2ecf20Sopenharmony_ci 0xea, 0x88, 0x89, 0x87, 0xef, 0x3f, 0x1e, 0x1e }; 35718c2ecf20Sopenharmony_ci u8 res[16]; 35728c2ecf20Sopenharmony_ci int err; 35738c2ecf20Sopenharmony_ci 35748c2ecf20Sopenharmony_ci err = smp_c1(k, r, preq, pres, _iat, &ia, _rat, &ra, res); 35758c2ecf20Sopenharmony_ci if (err) 35768c2ecf20Sopenharmony_ci return err; 35778c2ecf20Sopenharmony_ci 35788c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 16)) 35798c2ecf20Sopenharmony_ci return -EINVAL; 35808c2ecf20Sopenharmony_ci 35818c2ecf20Sopenharmony_ci return 0; 35828c2ecf20Sopenharmony_ci} 35838c2ecf20Sopenharmony_ci 35848c2ecf20Sopenharmony_cistatic int __init test_s1(void) 35858c2ecf20Sopenharmony_ci{ 35868c2ecf20Sopenharmony_ci const u8 k[16] = { 35878c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35888c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 35898c2ecf20Sopenharmony_ci const u8 r1[16] = { 35908c2ecf20Sopenharmony_ci 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }; 35918c2ecf20Sopenharmony_ci const u8 r2[16] = { 35928c2ecf20Sopenharmony_ci 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99 }; 35938c2ecf20Sopenharmony_ci const u8 exp[16] = { 35948c2ecf20Sopenharmony_ci 0x62, 0xa0, 0x6d, 0x79, 0xae, 0x16, 0x42, 0x5b, 35958c2ecf20Sopenharmony_ci 0x9b, 0xf4, 0xb0, 0xe8, 0xf0, 0xe1, 0x1f, 0x9a }; 35968c2ecf20Sopenharmony_ci u8 res[16]; 35978c2ecf20Sopenharmony_ci int err; 35988c2ecf20Sopenharmony_ci 35998c2ecf20Sopenharmony_ci err = smp_s1(k, r1, r2, res); 36008c2ecf20Sopenharmony_ci if (err) 36018c2ecf20Sopenharmony_ci return err; 36028c2ecf20Sopenharmony_ci 36038c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 16)) 36048c2ecf20Sopenharmony_ci return -EINVAL; 36058c2ecf20Sopenharmony_ci 36068c2ecf20Sopenharmony_ci return 0; 36078c2ecf20Sopenharmony_ci} 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_cistatic int __init test_f4(struct crypto_shash *tfm_cmac) 36108c2ecf20Sopenharmony_ci{ 36118c2ecf20Sopenharmony_ci const u8 u[32] = { 36128c2ecf20Sopenharmony_ci 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 36138c2ecf20Sopenharmony_ci 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 36148c2ecf20Sopenharmony_ci 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, 36158c2ecf20Sopenharmony_ci 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 }; 36168c2ecf20Sopenharmony_ci const u8 v[32] = { 36178c2ecf20Sopenharmony_ci 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b, 36188c2ecf20Sopenharmony_ci 0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59, 36198c2ecf20Sopenharmony_ci 0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90, 36208c2ecf20Sopenharmony_ci 0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 }; 36218c2ecf20Sopenharmony_ci const u8 x[16] = { 36228c2ecf20Sopenharmony_ci 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff, 36238c2ecf20Sopenharmony_ci 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 }; 36248c2ecf20Sopenharmony_ci const u8 z = 0x00; 36258c2ecf20Sopenharmony_ci const u8 exp[16] = { 36268c2ecf20Sopenharmony_ci 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1, 36278c2ecf20Sopenharmony_ci 0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 }; 36288c2ecf20Sopenharmony_ci u8 res[16]; 36298c2ecf20Sopenharmony_ci int err; 36308c2ecf20Sopenharmony_ci 36318c2ecf20Sopenharmony_ci err = smp_f4(tfm_cmac, u, v, x, z, res); 36328c2ecf20Sopenharmony_ci if (err) 36338c2ecf20Sopenharmony_ci return err; 36348c2ecf20Sopenharmony_ci 36358c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 16)) 36368c2ecf20Sopenharmony_ci return -EINVAL; 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci return 0; 36398c2ecf20Sopenharmony_ci} 36408c2ecf20Sopenharmony_ci 36418c2ecf20Sopenharmony_cistatic int __init test_f5(struct crypto_shash *tfm_cmac) 36428c2ecf20Sopenharmony_ci{ 36438c2ecf20Sopenharmony_ci const u8 w[32] = { 36448c2ecf20Sopenharmony_ci 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86, 36458c2ecf20Sopenharmony_ci 0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99, 36468c2ecf20Sopenharmony_ci 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, 36478c2ecf20Sopenharmony_ci 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec }; 36488c2ecf20Sopenharmony_ci const u8 n1[16] = { 36498c2ecf20Sopenharmony_ci 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff, 36508c2ecf20Sopenharmony_ci 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 }; 36518c2ecf20Sopenharmony_ci const u8 n2[16] = { 36528c2ecf20Sopenharmony_ci 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21, 36538c2ecf20Sopenharmony_ci 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 }; 36548c2ecf20Sopenharmony_ci const u8 a1[7] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56, 0x00 }; 36558c2ecf20Sopenharmony_ci const u8 a2[7] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7, 0x00 }; 36568c2ecf20Sopenharmony_ci const u8 exp_ltk[16] = { 36578c2ecf20Sopenharmony_ci 0x38, 0x0a, 0x75, 0x94, 0xb5, 0x22, 0x05, 0x98, 36588c2ecf20Sopenharmony_ci 0x23, 0xcd, 0xd7, 0x69, 0x11, 0x79, 0x86, 0x69 }; 36598c2ecf20Sopenharmony_ci const u8 exp_mackey[16] = { 36608c2ecf20Sopenharmony_ci 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd, 36618c2ecf20Sopenharmony_ci 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 }; 36628c2ecf20Sopenharmony_ci u8 mackey[16], ltk[16]; 36638c2ecf20Sopenharmony_ci int err; 36648c2ecf20Sopenharmony_ci 36658c2ecf20Sopenharmony_ci err = smp_f5(tfm_cmac, w, n1, n2, a1, a2, mackey, ltk); 36668c2ecf20Sopenharmony_ci if (err) 36678c2ecf20Sopenharmony_ci return err; 36688c2ecf20Sopenharmony_ci 36698c2ecf20Sopenharmony_ci if (crypto_memneq(mackey, exp_mackey, 16)) 36708c2ecf20Sopenharmony_ci return -EINVAL; 36718c2ecf20Sopenharmony_ci 36728c2ecf20Sopenharmony_ci if (crypto_memneq(ltk, exp_ltk, 16)) 36738c2ecf20Sopenharmony_ci return -EINVAL; 36748c2ecf20Sopenharmony_ci 36758c2ecf20Sopenharmony_ci return 0; 36768c2ecf20Sopenharmony_ci} 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_cistatic int __init test_f6(struct crypto_shash *tfm_cmac) 36798c2ecf20Sopenharmony_ci{ 36808c2ecf20Sopenharmony_ci const u8 w[16] = { 36818c2ecf20Sopenharmony_ci 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd, 36828c2ecf20Sopenharmony_ci 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 }; 36838c2ecf20Sopenharmony_ci const u8 n1[16] = { 36848c2ecf20Sopenharmony_ci 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff, 36858c2ecf20Sopenharmony_ci 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 }; 36868c2ecf20Sopenharmony_ci const u8 n2[16] = { 36878c2ecf20Sopenharmony_ci 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21, 36888c2ecf20Sopenharmony_ci 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 }; 36898c2ecf20Sopenharmony_ci const u8 r[16] = { 36908c2ecf20Sopenharmony_ci 0xc8, 0x0f, 0x2d, 0x0c, 0xd2, 0x42, 0xda, 0x08, 36918c2ecf20Sopenharmony_ci 0x54, 0xbb, 0x53, 0xb4, 0x3b, 0x34, 0xa3, 0x12 }; 36928c2ecf20Sopenharmony_ci const u8 io_cap[3] = { 0x02, 0x01, 0x01 }; 36938c2ecf20Sopenharmony_ci const u8 a1[7] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56, 0x00 }; 36948c2ecf20Sopenharmony_ci const u8 a2[7] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7, 0x00 }; 36958c2ecf20Sopenharmony_ci const u8 exp[16] = { 36968c2ecf20Sopenharmony_ci 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2, 36978c2ecf20Sopenharmony_ci 0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3 }; 36988c2ecf20Sopenharmony_ci u8 res[16]; 36998c2ecf20Sopenharmony_ci int err; 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci err = smp_f6(tfm_cmac, w, n1, n2, r, io_cap, a1, a2, res); 37028c2ecf20Sopenharmony_ci if (err) 37038c2ecf20Sopenharmony_ci return err; 37048c2ecf20Sopenharmony_ci 37058c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 16)) 37068c2ecf20Sopenharmony_ci return -EINVAL; 37078c2ecf20Sopenharmony_ci 37088c2ecf20Sopenharmony_ci return 0; 37098c2ecf20Sopenharmony_ci} 37108c2ecf20Sopenharmony_ci 37118c2ecf20Sopenharmony_cistatic int __init test_g2(struct crypto_shash *tfm_cmac) 37128c2ecf20Sopenharmony_ci{ 37138c2ecf20Sopenharmony_ci const u8 u[32] = { 37148c2ecf20Sopenharmony_ci 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 37158c2ecf20Sopenharmony_ci 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 37168c2ecf20Sopenharmony_ci 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, 37178c2ecf20Sopenharmony_ci 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 }; 37188c2ecf20Sopenharmony_ci const u8 v[32] = { 37198c2ecf20Sopenharmony_ci 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b, 37208c2ecf20Sopenharmony_ci 0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59, 37218c2ecf20Sopenharmony_ci 0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90, 37228c2ecf20Sopenharmony_ci 0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 }; 37238c2ecf20Sopenharmony_ci const u8 x[16] = { 37248c2ecf20Sopenharmony_ci 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff, 37258c2ecf20Sopenharmony_ci 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 }; 37268c2ecf20Sopenharmony_ci const u8 y[16] = { 37278c2ecf20Sopenharmony_ci 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21, 37288c2ecf20Sopenharmony_ci 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 }; 37298c2ecf20Sopenharmony_ci const u32 exp_val = 0x2f9ed5ba % 1000000; 37308c2ecf20Sopenharmony_ci u32 val; 37318c2ecf20Sopenharmony_ci int err; 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci err = smp_g2(tfm_cmac, u, v, x, y, &val); 37348c2ecf20Sopenharmony_ci if (err) 37358c2ecf20Sopenharmony_ci return err; 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci if (val != exp_val) 37388c2ecf20Sopenharmony_ci return -EINVAL; 37398c2ecf20Sopenharmony_ci 37408c2ecf20Sopenharmony_ci return 0; 37418c2ecf20Sopenharmony_ci} 37428c2ecf20Sopenharmony_ci 37438c2ecf20Sopenharmony_cistatic int __init test_h6(struct crypto_shash *tfm_cmac) 37448c2ecf20Sopenharmony_ci{ 37458c2ecf20Sopenharmony_ci const u8 w[16] = { 37468c2ecf20Sopenharmony_ci 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, 37478c2ecf20Sopenharmony_ci 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec }; 37488c2ecf20Sopenharmony_ci const u8 key_id[4] = { 0x72, 0x62, 0x65, 0x6c }; 37498c2ecf20Sopenharmony_ci const u8 exp[16] = { 37508c2ecf20Sopenharmony_ci 0x99, 0x63, 0xb1, 0x80, 0xe2, 0xa9, 0xd3, 0xe8, 37518c2ecf20Sopenharmony_ci 0x1c, 0xc9, 0x6d, 0xe7, 0x02, 0xe1, 0x9a, 0x2d }; 37528c2ecf20Sopenharmony_ci u8 res[16]; 37538c2ecf20Sopenharmony_ci int err; 37548c2ecf20Sopenharmony_ci 37558c2ecf20Sopenharmony_ci err = smp_h6(tfm_cmac, w, key_id, res); 37568c2ecf20Sopenharmony_ci if (err) 37578c2ecf20Sopenharmony_ci return err; 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_ci if (crypto_memneq(res, exp, 16)) 37608c2ecf20Sopenharmony_ci return -EINVAL; 37618c2ecf20Sopenharmony_ci 37628c2ecf20Sopenharmony_ci return 0; 37638c2ecf20Sopenharmony_ci} 37648c2ecf20Sopenharmony_ci 37658c2ecf20Sopenharmony_cistatic char test_smp_buffer[32]; 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_cistatic ssize_t test_smp_read(struct file *file, char __user *user_buf, 37688c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 37698c2ecf20Sopenharmony_ci{ 37708c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, test_smp_buffer, 37718c2ecf20Sopenharmony_ci strlen(test_smp_buffer)); 37728c2ecf20Sopenharmony_ci} 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_cistatic const struct file_operations test_smp_fops = { 37758c2ecf20Sopenharmony_ci .open = simple_open, 37768c2ecf20Sopenharmony_ci .read = test_smp_read, 37778c2ecf20Sopenharmony_ci .llseek = default_llseek, 37788c2ecf20Sopenharmony_ci}; 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_cistatic int __init run_selftests(struct crypto_shash *tfm_cmac, 37818c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh) 37828c2ecf20Sopenharmony_ci{ 37838c2ecf20Sopenharmony_ci ktime_t calltime, delta, rettime; 37848c2ecf20Sopenharmony_ci unsigned long long duration; 37858c2ecf20Sopenharmony_ci int err; 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci calltime = ktime_get(); 37888c2ecf20Sopenharmony_ci 37898c2ecf20Sopenharmony_ci err = test_debug_key(tfm_ecdh); 37908c2ecf20Sopenharmony_ci if (err) { 37918c2ecf20Sopenharmony_ci BT_ERR("debug_key test failed"); 37928c2ecf20Sopenharmony_ci goto done; 37938c2ecf20Sopenharmony_ci } 37948c2ecf20Sopenharmony_ci 37958c2ecf20Sopenharmony_ci err = test_ah(); 37968c2ecf20Sopenharmony_ci if (err) { 37978c2ecf20Sopenharmony_ci BT_ERR("smp_ah test failed"); 37988c2ecf20Sopenharmony_ci goto done; 37998c2ecf20Sopenharmony_ci } 38008c2ecf20Sopenharmony_ci 38018c2ecf20Sopenharmony_ci err = test_c1(); 38028c2ecf20Sopenharmony_ci if (err) { 38038c2ecf20Sopenharmony_ci BT_ERR("smp_c1 test failed"); 38048c2ecf20Sopenharmony_ci goto done; 38058c2ecf20Sopenharmony_ci } 38068c2ecf20Sopenharmony_ci 38078c2ecf20Sopenharmony_ci err = test_s1(); 38088c2ecf20Sopenharmony_ci if (err) { 38098c2ecf20Sopenharmony_ci BT_ERR("smp_s1 test failed"); 38108c2ecf20Sopenharmony_ci goto done; 38118c2ecf20Sopenharmony_ci } 38128c2ecf20Sopenharmony_ci 38138c2ecf20Sopenharmony_ci err = test_f4(tfm_cmac); 38148c2ecf20Sopenharmony_ci if (err) { 38158c2ecf20Sopenharmony_ci BT_ERR("smp_f4 test failed"); 38168c2ecf20Sopenharmony_ci goto done; 38178c2ecf20Sopenharmony_ci } 38188c2ecf20Sopenharmony_ci 38198c2ecf20Sopenharmony_ci err = test_f5(tfm_cmac); 38208c2ecf20Sopenharmony_ci if (err) { 38218c2ecf20Sopenharmony_ci BT_ERR("smp_f5 test failed"); 38228c2ecf20Sopenharmony_ci goto done; 38238c2ecf20Sopenharmony_ci } 38248c2ecf20Sopenharmony_ci 38258c2ecf20Sopenharmony_ci err = test_f6(tfm_cmac); 38268c2ecf20Sopenharmony_ci if (err) { 38278c2ecf20Sopenharmony_ci BT_ERR("smp_f6 test failed"); 38288c2ecf20Sopenharmony_ci goto done; 38298c2ecf20Sopenharmony_ci } 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci err = test_g2(tfm_cmac); 38328c2ecf20Sopenharmony_ci if (err) { 38338c2ecf20Sopenharmony_ci BT_ERR("smp_g2 test failed"); 38348c2ecf20Sopenharmony_ci goto done; 38358c2ecf20Sopenharmony_ci } 38368c2ecf20Sopenharmony_ci 38378c2ecf20Sopenharmony_ci err = test_h6(tfm_cmac); 38388c2ecf20Sopenharmony_ci if (err) { 38398c2ecf20Sopenharmony_ci BT_ERR("smp_h6 test failed"); 38408c2ecf20Sopenharmony_ci goto done; 38418c2ecf20Sopenharmony_ci } 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci rettime = ktime_get(); 38448c2ecf20Sopenharmony_ci delta = ktime_sub(rettime, calltime); 38458c2ecf20Sopenharmony_ci duration = (unsigned long long) ktime_to_ns(delta) >> 10; 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_ci BT_INFO("SMP test passed in %llu usecs", duration); 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_cidone: 38508c2ecf20Sopenharmony_ci if (!err) 38518c2ecf20Sopenharmony_ci snprintf(test_smp_buffer, sizeof(test_smp_buffer), 38528c2ecf20Sopenharmony_ci "PASS (%llu usecs)\n", duration); 38538c2ecf20Sopenharmony_ci else 38548c2ecf20Sopenharmony_ci snprintf(test_smp_buffer, sizeof(test_smp_buffer), "FAIL\n"); 38558c2ecf20Sopenharmony_ci 38568c2ecf20Sopenharmony_ci debugfs_create_file("selftest_smp", 0444, bt_debugfs, NULL, 38578c2ecf20Sopenharmony_ci &test_smp_fops); 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_ci return err; 38608c2ecf20Sopenharmony_ci} 38618c2ecf20Sopenharmony_ci 38628c2ecf20Sopenharmony_ciint __init bt_selftest_smp(void) 38638c2ecf20Sopenharmony_ci{ 38648c2ecf20Sopenharmony_ci struct crypto_shash *tfm_cmac; 38658c2ecf20Sopenharmony_ci struct crypto_kpp *tfm_ecdh; 38668c2ecf20Sopenharmony_ci int err; 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_ci tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); 38698c2ecf20Sopenharmony_ci if (IS_ERR(tfm_cmac)) { 38708c2ecf20Sopenharmony_ci BT_ERR("Unable to create CMAC crypto context"); 38718c2ecf20Sopenharmony_ci return PTR_ERR(tfm_cmac); 38728c2ecf20Sopenharmony_ci } 38738c2ecf20Sopenharmony_ci 38748c2ecf20Sopenharmony_ci tfm_ecdh = crypto_alloc_kpp("ecdh", 0, 0); 38758c2ecf20Sopenharmony_ci if (IS_ERR(tfm_ecdh)) { 38768c2ecf20Sopenharmony_ci BT_ERR("Unable to create ECDH crypto context"); 38778c2ecf20Sopenharmony_ci crypto_free_shash(tfm_cmac); 38788c2ecf20Sopenharmony_ci return PTR_ERR(tfm_ecdh); 38798c2ecf20Sopenharmony_ci } 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci err = run_selftests(tfm_cmac, tfm_ecdh); 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci crypto_free_shash(tfm_cmac); 38848c2ecf20Sopenharmony_ci crypto_free_kpp(tfm_ecdh); 38858c2ecf20Sopenharmony_ci 38868c2ecf20Sopenharmony_ci return err; 38878c2ecf20Sopenharmony_ci} 38888c2ecf20Sopenharmony_ci 38898c2ecf20Sopenharmony_ci#endif 3890