cregit-Linux how code gets into the kernel

Release 4.11 net/bluetooth/smp.c

Directory: net/bluetooth
/*
   BlueZ - Bluetooth protocol stack for Linux
   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation;

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
   SOFTWARE IS DISCLAIMED.
*/

#include <linux/debugfs.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <crypto/b128ops.h>
#include <crypto/hash.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>

#include "ecc.h"
#include "smp.h"


#define SMP_DEV(hdev) \
	((struct smp_dev *)((struct l2cap_chan *)((hdev)->smp_data))->data)

/* Low-level debug macros to be used for stuff that we don't want
 * accidentially in dmesg, i.e. the values of the various crypto keys
 * and the inputs & outputs of crypto functions.
 */
#ifdef DEBUG

#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
                                 ##__VA_ARGS__)
#else

#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
                                    ##__VA_ARGS__)
#endif


#define SMP_ALLOW_CMD(smp, code)	set_bit(code, &smp->allow_cmd)

/* Keys which are not distributed with Secure Connections */

#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);


#define SMP_TIMEOUT	msecs_to_jiffies(30000)


#define AUTH_REQ_MASK(dev)	(hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
                                 0x3f : 0x07)

#define KEY_DIST_MASK		0x07

/* Maximum message length that can be passed to aes_cmac */

#define CMAC_MSG_MAX	80

enum {
	
SMP_FLAG_TK_VALID,
	
SMP_FLAG_CFM_PENDING,
	
SMP_FLAG_MITM_AUTH,
	
SMP_FLAG_COMPLETE,
	
SMP_FLAG_INITIATOR,
	
SMP_FLAG_SC,
	
SMP_FLAG_REMOTE_PK,
	
SMP_FLAG_DEBUG_KEY,
	
SMP_FLAG_WAIT_USER,
	
SMP_FLAG_DHKEY_PENDING,
	
SMP_FLAG_REMOTE_OOB,
	
SMP_FLAG_LOCAL_OOB,
	
SMP_FLAG_CT2,
};


struct smp_dev {
	/* Secure Connections OOB data */
	
u8			local_pk[64];
	
u8			local_sk[32];
	
u8			local_rand[16];
	
bool			debug_key;

	
u8			min_key_size;
	
u8			max_key_size;

	
struct crypto_cipher	*tfm_aes;
	
struct crypto_shash	*tfm_cmac;
};


struct smp_chan {
	
struct l2cap_conn	*conn;
	
struct delayed_work	security_timer;
	
unsigned long           allow_cmd; /* Bitmask of allowed commands */

	
u8		preq[7]; /* SMP Pairing Request */
	
u8		prsp[7]; /* SMP Pairing Response */
	
u8		prnd[16]; /* SMP Pairing Random (local) */
	
u8		rrnd[16]; /* SMP Pairing Random (remote) */
	
u8		pcnf[16]; /* SMP Pairing Confirm */
	
u8		tk[16]; /* SMP Temporary Key */
	
u8		rr[16]; /* Remote OOB ra/rb value */
	
u8		lr[16]; /* Local OOB ra/rb value */
	
u8		enc_key_size;
	
u8		remote_key_dist;
	
bdaddr_t	id_addr;
	
u8		id_addr_type;
	
u8		irk[16];
	
struct smp_csrk	*csrk;
	
struct smp_csrk	*slave_csrk;
	
struct smp_ltk	*ltk;
	
struct smp_ltk	*slave_ltk;
	
struct smp_irk	*remote_irk;
	
u8		*link_key;
	
unsigned long	flags;
	
u8		method;
	
u8		passkey_round;

	/* Secure Connections variables */
	
u8			local_pk[64];
	
u8			local_sk[32];
	
u8			remote_pk[64];
	
u8			dhkey[32];
	
u8			mackey[16];

	
struct crypto_cipher	*tfm_aes;
	
struct crypto_shash	*tfm_cmac;
};

/* These debug key values are defined in the SMP section of the core
 * specification. debug_pk is the public debug key and debug_sk the
 * private debug key.
 */

static const u8 debug_pk[64] = {
		0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
		0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
		0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
		0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,

		0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
		0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
		0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
		0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
};


static const u8 debug_sk[32] = {
		0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
		0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
		0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
		0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
};


static inline void swap_buf(const u8 *src, u8 *dst, size_t len) { size_t i; for (i = 0; i < len; i++) dst[len - 1 - i] = src[i]; }

Contributors

PersonTokensPropCommitsCommitProp
Anderson Briglia3877.55%133.33%
Johan Hedberg1122.45%266.67%
Total49100.00%3100.00%

/* The following functions map to the LE SC SMP crypto functions * AES-CMAC, f4, f5, f6, g2 and h6. */
static int aes_cmac(struct crypto_shash *tfm, const u8 k[16], const u8 *m, size_t len, u8 mac[16]) { uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX]; SHASH_DESC_ON_STACK(desc, tfm); int err; if (len > CMAC_MSG_MAX) return -EFBIG; if (!tfm) { BT_ERR("tfm %p", tfm); return -EINVAL; } desc->tfm = tfm; desc->flags = 0; /* Swap key and message from LSB to MSB */ swap_buf(k, tmp, 16); swap_buf(m, msg_msb, len); SMP_DBG("msg (len %zu) %*phN", len, (int) len, m); SMP_DBG("key %16phN", k); err = crypto_shash_setkey(tfm, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; } err = crypto_shash_digest(desc, msg_msb, len, mac_msb); shash_desc_zero(desc); if (err) { BT_ERR("Hash computation error %d", err); return err; } swap_buf(mac_msb, mac, 16); SMP_DBG("mac %16phN", mac); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg20393.12%266.67%
Herbert Xu156.88%133.33%
Total218100.00%3100.00%


static int smp_f4(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 v[32], const u8 x[16], u8 z, u8 res[16]) { u8 m[65]; int err; SMP_DBG("u %32phN", u); SMP_DBG("v %32phN", v); SMP_DBG("x %16phN z %02x", x, z); m[0] = z; memcpy(m + 1, v, 32); memcpy(m + 33, u, 32); err = aes_cmac(tfm_cmac, x, m, sizeof(m), res); if (err) return err; SMP_DBG("res %16phN", res); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg13699.27%266.67%
Herbert Xu10.73%133.33%
Total137100.00%3100.00%


static int smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32], const u8 n1[16], const u8 n2[16], const u8 a1[7], const u8 a2[7], u8 mackey[16], u8 ltk[16]) { /* The btle, salt and length "magic" values are as defined in * the SMP section of the Bluetooth core specification. In ASCII * the btle value ends up being 'btle'. The salt is just a * random number whereas length is the value 256 in little * endian format. */ const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 }; const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60, 0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c }; const u8 length[2] = { 0x00, 0x01 }; u8 m[53], t[16]; int err; SMP_DBG("w %32phN", w); SMP_DBG("n1 %16phN n2 %16phN", n1, n2); SMP_DBG("a1 %7phN a2 %7phN", a1, a2); err = aes_cmac(tfm_cmac, salt, w, 32, t); if (err) return err; SMP_DBG("t %16phN", t); memcpy(m, length, 2); memcpy(m + 2, a2, 7); memcpy(m + 9, a1, 7); memcpy(m + 16, n2, 16); memcpy(m + 32, n1, 16); memcpy(m + 48, btle, 4); m[52] = 0; /* Counter */ err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey); if (err) return err; SMP_DBG("mackey %16phN", mackey); m[52] = 1; /* Counter */ err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk); if (err) return err; SMP_DBG("ltk %16phN", ltk); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg34499.71%480.00%
Herbert Xu10.29%120.00%
Total345100.00%5100.00%


static int smp_f6(struct crypto_shash *tfm_cmac, const u8 w[16], const u8 n1[16], const u8 n2[16], const u8 r[16], const u8 io_cap[3], const u8 a1[7], const u8 a2[7], u8 res[16]) { u8 m[65]; int err; SMP_DBG("w %16phN", w); SMP_DBG("n1 %16phN n2 %16phN", n1, n2); SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2); memcpy(m, a2, 7); memcpy(m + 7, a1, 7); memcpy(m + 14, io_cap, 3); memcpy(m + 17, r, 16); memcpy(m + 33, n2, 16); memcpy(m + 49, n1, 16); err = aes_cmac(tfm_cmac, w, m, sizeof(m), res); if (err) return err; SMP_DBG("res %16phN", res); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg15777.34%562.50%
Anderson Briglia4421.67%112.50%
Marcel Holtmann10.49%112.50%
Herbert Xu10.49%112.50%
Total203100.00%8100.00%


static int smp_g2(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 v[32], const u8 x[16], const u8 y[16], u32 *val) { u8 m[80], tmp[16]; int err; SMP_DBG("u %32phN", u); SMP_DBG("v %32phN", v); SMP_DBG("x %16phN y %16phN", x, y); memcpy(m, y, 16); memcpy(m + 16, v, 32); memcpy(m + 48, u, 32); err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp); if (err) return err; *val = get_unaligned_le32(tmp); *val %= 1000000; SMP_DBG("val %06u", *val); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg15999.38%480.00%
Herbert Xu10.62%120.00%
Total160100.00%5100.00%


static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16], const u8 key_id[4], u8 res[16]) { int err; SMP_DBG("w %16phN key_id %4phN", w, key_id); err = aes_cmac(tfm_cmac, w, key_id, 4, res); if (err) return err; SMP_DBG("res %16phN", res); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg7498.67%150.00%
Herbert Xu11.33%150.00%
Total75100.00%2100.00%


static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16], const u8 salt[16], u8 res[16]) { int err; SMP_DBG("w %16phN salt %16phN", w, salt); err = aes_cmac(tfm_cmac, salt, w, 16, res); if (err) return err; SMP_DBG("res %16phN", res); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg75100.00%1100.00%
Total75100.00%1100.00%

/* The following functions map to the legacy SMP crypto functions e, c1, * s1 and ah. */
static int smp_e(struct crypto_cipher *tfm, const u8 *k, u8 *r) { uint8_t tmp[16], data[16]; int err; SMP_DBG("k %16phN r %16phN", k, r); if (!tfm) { BT_ERR("tfm %p", tfm); return -EINVAL; } /* The most significant octet of key corresponds to k[0] */ swap_buf(k, tmp, 16); err = crypto_cipher_setkey(tfm, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; } /* Most significant octet of plaintextData corresponds to data[0] */ swap_buf(r, data, 16); crypto_cipher_encrypt_one(tfm, data, data); /* Most significant octet of encryptedData corresponds to data[0] */ swap_buf(data, r, 16); SMP_DBG("r %16phN", r); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg13195.62%571.43%
Andrew Lutomirski53.65%114.29%
Herbert Xu10.73%114.29%
Total137100.00%7100.00%


static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16], const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat, const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16]) { u8 p1[16], p2[16]; int err; SMP_DBG("k %16phN r %16phN", k, r); SMP_DBG("iat %u ia %6phN rat %u ra %6phN", _iat, ia, _rat, ra); SMP_DBG("preq %7phN pres %7phN", preq, pres); memset(p1, 0, 16); /* p1 = pres || preq || _rat || _iat */ p1[0] = _iat; p1[1] = _rat; memcpy(p1 + 2, preq, 7); memcpy(p1 + 9, pres, 7); SMP_DBG("p1 %16phN", p1); /* res = r XOR p1 */ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); /* res = e(k, res) */ err = smp_e(tfm_aes, k, res); if (err) { BT_ERR("Encrypt data error"); return err; } /* p2 = padding || ia || ra */ memcpy(p2, ra, 6); memcpy(p2 + 6, ia, 6); memset(p2 + 12, 0, 4); SMP_DBG("p2 %16phN", p2); /* res = res XOR p2 */ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); /* res = e(k, res) */ err = smp_e(tfm_aes, k, res); if (err) BT_ERR("Encrypt data error"); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg29199.66%787.50%
Andrew Lutomirski10.34%112.50%
Total292100.00%8100.00%


static int smp_s1(struct crypto_cipher *tfm_aes, const u8 k[16], const u8 r1[16], const u8 r2[16], u8 _r[16]) { int err; /* Just least significant octets from r1 and r2 are considered */ memcpy(_r, r2, 8); memcpy(_r + 8, r1, 8); err = smp_e(tfm_aes, k, _r); if (err) BT_ERR("Encrypt data error"); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Anderson Briglia5868.24%114.29%
Johan Hedberg2630.59%571.43%
Andrew Lutomirski11.18%114.29%
Total85100.00%7100.00%


static int smp_ah(struct crypto_cipher *tfm, const u8 irk[16], const u8 r[3], u8 res[3]) { u8 _res[16]; int err; /* r' = padding || r */ memcpy(_res, r, 3); memset(_res + 3, 0, 13); err = smp_e(tfm, irk, _res); if (err) { BT_ERR("Encrypt error"); return err; } /* The output of the random address function ah is: * ah(k, r) = e(k, r') mod 2^24 * The output of the security function e is then truncated to 24 bits * by taking the least significant 24 bits of the output of e as the * result of ah. */ memcpy(res, _res, 3); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg7272.73%125.00%
Anderson Briglia2525.25%125.00%
Marcel Holtmann11.01%125.00%
Andrew Lutomirski11.01%125.00%
Total99100.00%4100.00%


bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], const bdaddr_t *bdaddr) { struct l2cap_chan *chan = hdev->smp_data; struct smp_dev *smp; u8 hash[3]; int err; if (!chan || !chan->data) return false; smp = chan->data; BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk); err = smp_ah(smp->tfm_aes, irk, &bdaddr->b[3], hash); if (err) return false; return !memcmp(bdaddr->b, hash, 3); }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg9783.62%250.00%
Anderson Briglia1311.21%125.00%
Marcel Holtmann65.17%125.00%
Total116100.00%4100.00%


int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) { struct l2cap_chan *chan = hdev->smp_data; struct smp_dev *smp; int err; if (!chan || !chan->data) return -EOPNOTSUPP; smp = chan->data; get_random_bytes(&rpa->b[3], 3); rpa->b[5] &= 0x3f; /* Clear two most significant bits */ rpa->b[5] |= 0x40; /* Set second most significant bit */ err = smp_ah(smp->tfm_aes, irk, &rpa->b[3], rpa->b); if (err < 0) return err; BT_DBG("RPA %pMR", rpa); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hedberg9470.68%250.00%
Anderson Briglia3324.81%125.00%
Marcel Holtmann64.51%125.00%
Total133100.00%4100.00%


int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) { struct l2cap_chan *chan = hdev->smp_data; struct smp_dev *smp; int err; if (!chan || !chan->data) return -EOPNOTSUPP; smp = chan->data; if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) { BT_DBG("Using debug keys"); memcpy(smp->local_pk, debug_pk, 64); memcpy(smp->local_sk, debug_sk, 32); smp->debug_key = true; } else { while (true) { /* Generate local key pair for Secure Connections */ if (!ecc_make_key(smp->local_pk, smp->local_sk)) return -EIO; /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ if (memcmp(smp->local_sk, debug_sk, 32)) break; } smp->debug_key = false; } SMP_DBG("OOB Public Key X: %32phN", smp->local_pk); SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32); SMP_DBG("OOB Private Key: %32phN", smp->local_sk); get_random_bytes(smp->local_rand, 16); err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk, smp->local_rand, 0, hash); if (err < 0) return err; memcpy(rand, smp->local_rand, 16); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Marcel Holtmann238100.00%2100.00%
Total238100.00%2100.00%


static void smp_send_cmd(struct l2cap_conn *conn, u8 code