Release 4.11 net/bluetooth/smp.c
/*
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
Person | Tokens | Prop | Commits | CommitProp |
Anderson Briglia | 38 | 77.55% | 1 | 33.33% |
Johan Hedberg | 11 | 22.45% | 2 | 66.67% |
Total | 49 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 203 | 93.12% | 2 | 66.67% |
Herbert Xu | 15 | 6.88% | 1 | 33.33% |
Total | 218 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 136 | 99.27% | 2 | 66.67% |
Herbert Xu | 1 | 0.73% | 1 | 33.33% |
Total | 137 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 344 | 99.71% | 4 | 80.00% |
Herbert Xu | 1 | 0.29% | 1 | 20.00% |
Total | 345 | 100.00% | 5 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 157 | 77.34% | 5 | 62.50% |
Anderson Briglia | 44 | 21.67% | 1 | 12.50% |
Marcel Holtmann | 1 | 0.49% | 1 | 12.50% |
Herbert Xu | 1 | 0.49% | 1 | 12.50% |
Total | 203 | 100.00% | 8 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 159 | 99.38% | 4 | 80.00% |
Herbert Xu | 1 | 0.62% | 1 | 20.00% |
Total | 160 | 100.00% | 5 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 74 | 98.67% | 1 | 50.00% |
Herbert Xu | 1 | 1.33% | 1 | 50.00% |
Total | 75 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 75 | 100.00% | 1 | 100.00% |
Total | 75 | 100.00% | 1 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 131 | 95.62% | 5 | 71.43% |
Andrew Lutomirski | 5 | 3.65% | 1 | 14.29% |
Herbert Xu | 1 | 0.73% | 1 | 14.29% |
Total | 137 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 291 | 99.66% | 7 | 87.50% |
Andrew Lutomirski | 1 | 0.34% | 1 | 12.50% |
Total | 292 | 100.00% | 8 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Anderson Briglia | 58 | 68.24% | 1 | 14.29% |
Johan Hedberg | 26 | 30.59% | 5 | 71.43% |
Andrew Lutomirski | 1 | 1.18% | 1 | 14.29% |
Total | 85 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 72 | 72.73% | 1 | 25.00% |
Anderson Briglia | 25 | 25.25% | 1 | 25.00% |
Marcel Holtmann | 1 | 1.01% | 1 | 25.00% |
Andrew Lutomirski | 1 | 1.01% | 1 | 25.00% |
Total | 99 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 97 | 83.62% | 2 | 50.00% |
Anderson Briglia | 13 | 11.21% | 1 | 25.00% |
Marcel Holtmann | 6 | 5.17% | 1 | 25.00% |
Total | 116 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Johan Hedberg | 94 | 70.68% | 2 | 50.00% |
Anderson Briglia | 33 | 24.81% | 1 | 25.00% |
Marcel Holtmann | 6 | 4.51% | 1 | 25.00% |
Total | 133 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Marcel Holtmann | 238 | 100.00% | 2 | 100.00% |
Total | 238 | 100.00% | 2 | 100.00% |
static void smp_send_cmd(struct l2cap_conn *conn, u8 code