Bluetooth: Split keys into LE and BR/EDR specific storage

This make LE and BR/EDR keys store in separate storages. This is
to simplify handling of dual mode device handling where identity
information are distributed after LTK. BR/EDR has only one key
(Link Key) so this transport specific code can be further simplified.

Change-Id: I8f45d4491ce613aaac11f1d60cf42c38fc3eceec
Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
This commit is contained in:
Szymon Janc 2016-08-08 16:40:30 +02:00 committed by Johan Hedberg
commit 60691c4650
8 changed files with 253 additions and 237 deletions

View file

@ -11,17 +11,13 @@ obj-$(CONFIG_BLUETOOTH_DEBUG_MONITOR) += monitor.o
obj-$(CONFIG_BLUETOOTH_TINYCRYPT_ECC) += hci_ecc.o
ifeq ($(CONFIG_BLUETOOTH_CONN),y)
obj-y += conn.o \
l2cap.o \
att.o \
gatt.o
obj-y += conn.o l2cap.o att.o gatt.o
ifeq ($(CONFIG_BLUETOOTH_SMP),y)
obj-y += smp.o \
keys.o
obj-y += smp.o keys.o
else
obj-y += smp_null.o
endif
obj-$(CONFIG_BLUETOOTH_BREDR) += keys.o l2cap_br.o
obj-$(CONFIG_BLUETOOTH_BREDR) += keys_br.o l2cap_br.o
endif

View file

@ -618,7 +618,17 @@ int bt_conn_le_start_encryption(struct bt_conn *conn, uint64_t rand,
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
uint8_t bt_conn_enc_key_size(struct bt_conn *conn)
{
return conn->keys ? conn->keys->enc_size : 0;
#if defined(CONFIG_BLUETOOTH_BREDR)
if (conn->type == BT_CONN_TYPE_BR) {
return conn->br.link_key ? 16 : 0;
}
#endif /* CONFIG_BLUETOOTH_BREDR */
#if defined(CONFIG_BLUETOOTH_SMP)
return conn->le.keys ? conn->le.keys->enc_size : 0;
#else
return 0;
#endif /* CONFIG_BLUETOOTH_SMP */
}
void bt_conn_security_changed(struct bt_conn *conn)
@ -657,38 +667,39 @@ static int start_security(struct bt_conn *conn)
#if defined(CONFIG_BLUETOOTH_CENTRAL) && defined(CONFIG_BLUETOOTH_SMP)
case BT_HCI_ROLE_MASTER:
{
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_LTK_P256,
&conn->le.dst);
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_LTK,
&conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256,
&conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK,
&conn->le.dst);
}
}
if (!conn->keys ||
!(conn->keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) {
if (!conn->le.keys ||
!(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) {
return bt_smp_send_pairing_req(conn);
}
if (conn->required_sec_level > BT_SECURITY_MEDIUM &&
!atomic_test_bit(conn->keys->flags,
!atomic_test_bit(conn->le.keys->flags,
BT_KEYS_AUTHENTICATED)) {
return bt_smp_send_pairing_req(conn);
}
if (conn->required_sec_level > BT_SECURITY_HIGH &&
!atomic_test_bit(conn->keys->flags,
!atomic_test_bit(conn->le.keys->flags,
BT_KEYS_AUTHENTICATED) &&
!(conn->keys->keys & BT_KEYS_LTK_P256)) {
!(conn->le.keys->keys & BT_KEYS_LTK_P256)) {
return bt_smp_send_pairing_req(conn);
}
/* LE SC LTK and legacy master LTK are stored in same place */
return bt_conn_le_start_encryption(conn, conn->keys->ltk.rand,
conn->keys->ltk.ediv,
conn->keys->ltk.val,
conn->keys->enc_size);
return bt_conn_le_start_encryption(conn,
conn->le.keys->ltk.rand,
conn->le.keys->ltk.ediv,
conn->le.keys->ltk.val,
conn->le.keys->enc_size);
}
#endif /* CONFIG_BLUETOOTH_CENTRAL && CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_PERIPHERAL) && defined(CONFIG_BLUETOOTH_SMP)

View file

@ -53,6 +53,8 @@ struct bt_conn_le {
uint8_t features[8];
struct bt_keys *keys;
/* Delayed work for connection update handling */
struct nano_delayed_work update_work;
};
@ -76,6 +78,8 @@ struct bt_conn_br {
uint8_t pairing_method;
/* remote LMP features pages per 8 bytes each */
uint8_t features[LMP_MAX_PAGES][8];
struct bt_keys_link_key *link_key;
};
#endif
@ -100,8 +104,6 @@ struct bt_conn {
/* Queue for outgoing ACL data */
struct nano_fifo tx_queue;
struct bt_keys *keys;
/* L2CAP channels */
void *channels;

View file

@ -635,7 +635,7 @@ static void hci_disconn_complete(struct net_buf *buf)
*/
if (conn->type == BT_CONN_TYPE_BR &&
atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND)) {
bt_keys_clear(conn->keys, BT_KEYS_LINK_KEY);
bt_keys_link_key_clear(conn->br.link_key);
}
#endif
bt_conn_unref(conn);
@ -1105,11 +1105,12 @@ static void update_sec_level_br(struct bt_conn *conn)
return;
}
if (conn->keys && (conn->keys->keys & BT_KEYS_LINK_KEY)) {
conn->sec_level = BT_SECURITY_MEDIUM;
if (atomic_test_bit(conn->keys->flags,
BT_KEYS_AUTHENTICATED)) {
if (conn->br.link_key) {
if (atomic_test_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED)) {
conn->sec_level = BT_SECURITY_HIGH;
} else {
conn->sec_level = BT_SECURITY_MEDIUM;
}
} else {
BT_WARN("No BR/EDR link key found");
@ -1192,10 +1193,10 @@ static void link_key_notify(struct net_buf *buf)
BT_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type);
if (!conn->keys) {
conn->keys = bt_keys_get_link_key(&evt->bdaddr);
if (!conn->br.link_key) {
conn->br.link_key = bt_keys_get_link_key(&evt->bdaddr);
}
if (!conn->keys) {
if (!conn->br.link_key) {
BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr));
bt_conn_unref(conn);
return;
@ -1209,16 +1210,16 @@ static void link_key_notify(struct net_buf *buf)
*/
if (atomic_test_and_clear_bit(conn->flags,
BT_CONN_BR_LEGACY_SECURE)) {
atomic_set_bit(conn->keys->flags,
BT_KEYS_AUTHENTICATED);
atomic_set_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED);
}
memcpy(conn->keys->link_key.val, evt->link_key, 16);
memcpy(conn->br.link_key->val, evt->link_key, 16);
break;
case BT_LK_UNAUTH_COMBINATION_P192:
case BT_LK_AUTH_COMBINATION_P192:
if (evt->key_type == BT_LK_AUTH_COMBINATION_P192) {
atomic_set_bit(conn->keys->flags,
BT_KEYS_AUTHENTICATED);
atomic_set_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED);
}
/*
* Update keys database if authentication bond is required to
@ -1226,7 +1227,7 @@ static void link_key_notify(struct net_buf *buf)
* the contrary.
*/
if (bt_conn_ssp_get_auth(conn) > BT_HCI_NO_BONDING_MITM) {
memcpy(conn->keys->link_key.val, evt->link_key, 16);
memcpy(conn->br.link_key->val, evt->link_key, 16);
} else {
atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND);
}
@ -1290,11 +1291,11 @@ static void link_key_req(struct net_buf *buf)
return;
}
if (!conn->keys) {
conn->keys = bt_keys_find_link_key(&evt->bdaddr);
if (!conn->br.link_key) {
conn->br.link_key = bt_keys_find_link_key(&evt->bdaddr);
}
if (!conn->keys) {
if (!conn->br.link_key) {
link_key_neg_reply(&evt->bdaddr);
bt_conn_unref(conn);
return;
@ -1304,14 +1305,15 @@ static void link_key_req(struct net_buf *buf)
* Enforce regenerate by controller stronger link key since found one
* in database not covers requested security level.
*/
if (!atomic_test_bit(conn->keys->flags, BT_KEYS_AUTHENTICATED) &&
if (!atomic_test_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED) &&
conn->required_sec_level > BT_SECURITY_MEDIUM) {
link_key_neg_reply(&evt->bdaddr);
bt_conn_unref(conn);
return;
}
link_key_reply(&evt->bdaddr, conn->keys->link_key.val);
link_key_reply(&evt->bdaddr, conn->br.link_key->val);
bt_conn_unref(conn);
}
@ -1886,7 +1888,7 @@ static void read_remote_ext_features_complete(struct net_buf *buf)
#endif /* CONFIG_BLUETOOTH_BREDR */
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
#if defined(CONFIG_BLUETOOTH_SMP)
static void update_sec_level(struct bt_conn *conn)
{
if (!conn->encrypt) {
@ -1894,9 +1896,9 @@ static void update_sec_level(struct bt_conn *conn)
return;
}
if (conn->keys && atomic_test_bit(conn->keys->flags,
BT_KEYS_AUTHENTICATED)) {
if (conn->keys->keys & BT_KEYS_LTK_P256) {
if (conn->le.keys && atomic_test_bit(conn->le.keys->flags,
BT_KEYS_AUTHENTICATED)) {
if (conn->le.keys->keys & BT_KEYS_LTK_P256) {
conn->sec_level = BT_SECURITY_FIPS;
} else {
conn->sec_level = BT_SECURITY_HIGH;
@ -1910,7 +1912,9 @@ static void update_sec_level(struct bt_conn *conn)
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
}
}
#endif /* CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
static void hci_encrypt_change(struct net_buf *buf)
{
struct bt_hci_evt_encrypt_change *evt = (void *)buf->data;
@ -1942,26 +1946,28 @@ static void hci_encrypt_change(struct net_buf *buf)
conn->encrypt = evt->encrypt;
/*
* we update keys properties only on successful encryption to avoid
* losing valid keys if encryption was not successful
*
* Update keys with last pairing info for proper sec level update.
* This is done only for LE transport, for BR/EDR keys are updated on
* HCI 'Link Key Notification Event'
*/
if (conn->encrypt && conn->type == BT_CONN_TYPE_LE) {
bt_smp_update_keys(conn);
}
#if defined(CONFIG_BLUETOOTH_SMP)
if (conn->type == BT_CONN_TYPE_LE) {
/*
* we update keys properties only on successful encryption to
* avoid losing valid keys if encryption was not successful.
*
* Update keys with last pairing info for proper sec level
* update. This is done only for LE transport, for BR/EDR keys
* are updated on HCI 'Link Key Notification Event'
*/
if (conn->encrypt) {
bt_smp_update_keys(conn);
}
update_sec_level(conn);
}
#endif /* CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_BREDR)
} else {
if (conn->type == BT_CONN_TYPE_BR) {
update_sec_level_br(conn);
reset_pairing(conn);
#endif /* CONFIG_BLUETOOTH_BREDR */
}
#endif /* CONFIG_BLUETOOTH_BREDR */
bt_l2cap_encrypt_change(conn);
bt_conn_security_changed(conn);
@ -1995,14 +2001,17 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
* updated on HCI 'Link Key Notification Event', therefore update here
* only security level based on available keys and encryption state.
*/
#if defined(CONFIG_BLUETOOTH_SMP)
if (conn->type == BT_CONN_TYPE_LE) {
bt_smp_update_keys(conn);
update_sec_level(conn);
#if defined(CONFIG_BLUETOOTH_BREDR)
} else {
update_sec_level_br(conn);
#endif /* CONFIG_BLUETOOTH_BREDR */
}
#endif /* CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_BREDR)
if (conn->type == BT_CONN_TYPE_BR) {
update_sec_level_br(conn);
}
#endif /* CONFIG_BLUETOOTH_BREDR */
bt_l2cap_encrypt_change(conn);
bt_conn_security_changed(conn);
@ -2053,15 +2062,15 @@ static void le_ltk_request(struct net_buf *buf)
goto done;
}
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_LTK_P256, &conn->le.dst);
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_SLAVE_LTK,
&conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, &conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_SLAVE_LTK,
&conn->le.dst);
}
}
if (conn->keys && (conn->keys->keys & BT_KEYS_LTK_P256) &&
if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_LTK_P256) &&
evt->rand == 0 && evt->ediv == 0) {
struct bt_hci_cp_le_ltk_req_reply *cp;
@ -2076,10 +2085,11 @@ static void le_ltk_request(struct net_buf *buf)
cp->handle = evt->handle;
/* use only enc_size bytes of key for encryption */
memcpy(cp->ltk, conn->keys->ltk.val, conn->keys->enc_size);
if (conn->keys->enc_size < sizeof(cp->ltk)) {
memset(cp->ltk + conn->keys->enc_size, 0,
sizeof(cp->ltk) - conn->keys->enc_size);
memcpy(cp->ltk, conn->le.keys->ltk.val,
conn->le.keys->enc_size);
if (conn->le.keys->enc_size < sizeof(cp->ltk)) {
memset(cp->ltk + conn->le.keys->enc_size, 0,
sizeof(cp->ltk) - conn->le.keys->enc_size);
}
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
@ -2087,9 +2097,9 @@ static void le_ltk_request(struct net_buf *buf)
}
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
if (conn->keys && (conn->keys->keys & BT_KEYS_SLAVE_LTK) &&
conn->keys->slave_ltk.rand == evt->rand &&
conn->keys->slave_ltk.ediv == evt->ediv) {
if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) &&
conn->le.keys->slave_ltk.rand == evt->rand &&
conn->le.keys->slave_ltk.ediv == evt->ediv) {
struct bt_hci_cp_le_ltk_req_reply *cp;
struct net_buf *buf;
@ -2104,11 +2114,11 @@ static void le_ltk_request(struct net_buf *buf)
cp->handle = evt->handle;
/* use only enc_size bytes of key for encryption */
memcpy(cp->ltk, conn->keys->slave_ltk.val,
conn->keys->enc_size);
if (conn->keys->enc_size < sizeof(cp->ltk)) {
memset(cp->ltk + conn->keys->enc_size, 0,
sizeof(cp->ltk) - conn->keys->enc_size);
memcpy(cp->ltk, conn->le.keys->slave_ltk.val,
conn->le.keys->enc_size);
if (conn->le.keys->enc_size < sizeof(cp->ltk)) {
memset(cp->ltk + conn->le.keys->enc_size, 0,
sizeof(cp->ltk) - conn->le.keys->enc_size);
}
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);

View file

@ -38,7 +38,6 @@
static struct bt_keys key_pool[CONFIG_BLUETOOTH_MAX_PAIRED];
#if defined(CONFIG_BLUETOOTH_SMP)
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr)
{
struct bt_keys *keys;
@ -159,105 +158,16 @@ struct bt_keys *bt_keys_find_addr(const bt_addr_le_t *addr)
return NULL;
}
#endif /* CONFIG_BLUETOOTH_SMP */
void bt_keys_add_type(struct bt_keys *keys, int type)
{
keys->keys |= type;
}
void bt_keys_clear(struct bt_keys *keys, int type)
void bt_keys_clear(struct bt_keys *keys)
{
BT_DBG("keys for %s type %d", bt_addr_le_str(&keys->addr), type);
BT_DBG("keys for %s", bt_addr_le_str(&keys->addr));
keys->keys &= ~type;
if (!keys->keys) {
memset(keys, 0, sizeof(*keys));
}
memset(keys, 0, sizeof(*keys));
}
#if defined(CONFIG_BLUETOOTH_BREDR)
static struct bt_keys *bt_keys_get_addr_br(const bt_addr_t *addr)
{
struct bt_keys *keys;
int i;
BT_DBG("%s", bt_addr_str(addr));
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
keys = &key_pool[i];
/*
* When both LE and BR/EDR keys are for the same device,
* the bt_addr_le_t is the public address, i.e. the same
* as the BR/EDR address.
*/
if (keys->addr.type == BT_ADDR_LE_PUBLIC &&
!bt_addr_cmp(&keys->addr.a, addr)) {
return keys;
}
/*
* BT_ADDR_LE_ANY has the same type of as BT_ADDR_LE_PUBLIC
* value. No need to make redundant comparison against
* BT_ADDR_LE_PUBLIC.
*/
if (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) {
bt_addr_copy(&keys->addr.a, addr);
BT_DBG("created %p for %s", keys, bt_addr_str(addr));
return keys;
}
}
BT_DBG("unable to create keys for %s", bt_addr_str(addr));
return NULL;
}
struct bt_keys *bt_keys_find_link_key(const bt_addr_t *addr)
{
struct bt_keys *keys;
int i;
BT_DBG("%s", bt_addr_str(addr));
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
keys = &key_pool[i];
/*
* When both LE and BR/EDR keys are for the same device,
* the bt_addr_le_t is the public address, i.e. the same
* as the BR/EDR address.
*/
if (keys->addr.type == BT_ADDR_LE_PUBLIC &&
(keys->keys & BT_KEYS_LINK_KEY) &&
!bt_addr_cmp(&keys->addr.a, addr)) {
return keys;
}
}
return NULL;
}
struct bt_keys *bt_keys_get_link_key(const bt_addr_t *addr)
{
struct bt_keys *keys;
BT_DBG("%s", bt_addr_str(addr));
keys = bt_keys_find_link_key(addr);
if (keys) {
return keys;
}
keys = bt_keys_get_addr_br(addr);
if (!keys) {
return NULL;
}
bt_keys_add_type(keys, BT_KEYS_LINK_KEY);
return keys;
}
#endif /* CONFIG_BLUETOOTH_BREDR */

View file

@ -16,7 +16,7 @@
* limitations under the License.
*/
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
#if defined(CONFIG_BLUETOOTH_SMP)
enum {
BT_KEYS_SLAVE_LTK = BIT(0),
BT_KEYS_IRK = BIT(1),
@ -24,12 +24,10 @@ enum {
BT_KEYS_LOCAL_CSRK = BIT(3),
BT_KEYS_REMOTE_CSRK = BIT(4),
BT_KEYS_LTK_P256 = BIT(5),
BT_KEYS_LINK_KEY = BIT(6),
BT_KEYS_ALL = (BT_KEYS_SLAVE_LTK | BT_KEYS_IRK | \
BT_KEYS_LTK | BT_KEYS_LOCAL_CSRK | \
BT_KEYS_REMOTE_CSRK | BT_KEYS_LTK_P256 | \
BT_KEYS_LINK_KEY),
BT_KEYS_REMOTE_CSRK | BT_KEYS_LTK_P256),
};
enum {
@ -56,46 +54,48 @@ struct bt_csrk {
uint32_t cnt;
};
struct bt_link_key {
uint8_t val[16];
};
struct bt_keys {
bt_addr_le_t addr;
uint8_t enc_size;
ATOMIC_DEFINE(flags, BT_KEYS_NUM_FLAGS);
uint16_t keys;
#if defined(CONFIG_BLUETOOTH_SMP)
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
struct bt_ltk slave_ltk;
#endif /* CONFIG_BLUETOOTH_SMP_SC_ONLY */
struct bt_ltk ltk;
struct bt_irk irk;
#if defined(CONFIG_BLUETOOTH_SIGNING)
struct bt_csrk local_csrk;
struct bt_csrk remote_csrk;
#endif /* BLUETOOTH_SIGNING */
#endif /* CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_BREDR)
struct bt_link_key link_key;
#endif /* CONFIG_BLUETOOTH_BREDR */
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
struct bt_ltk slave_ltk;
#endif /* CONFIG_BLUETOOTH_SMP_SC_ONLY */
};
#if defined(CONFIG_BLUETOOTH_BREDR)
struct bt_keys *bt_keys_get_link_key(const bt_addr_t *addr);
struct bt_keys *bt_keys_find_link_key(const bt_addr_t *addr);
#endif /* CONFIG_BLUETOOTH_BREDR */
#if defined(CONFIG_BLUETOOTH_SMP)
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr);
struct bt_keys *bt_keys_get_type(int type, const bt_addr_le_t *addr);
struct bt_keys *bt_keys_find(int type, const bt_addr_le_t *addr);
struct bt_keys *bt_keys_find_irk(const bt_addr_le_t *addr);
struct bt_keys *bt_keys_find_addr(const bt_addr_le_t *addr);
#endif /* CONFIG_BLUETOOTH_SMP */
void bt_keys_add_type(struct bt_keys *keys, int type);
void bt_keys_clear(struct bt_keys *keys, int type);
#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */
void bt_keys_clear(struct bt_keys *keys);
#endif /* CONFIG_BLUETOOTH_SMP */
#if defined(CONFIG_BLUETOOTH_BREDR)
enum {
BT_LINK_KEY_AUTHENTICATED,
BT_LINK_KEY_DEBUG,
/* Total number of flags - must be at the end of the enum */
BT_LINK_KEY_NUM_FLAGS,
};
struct bt_keys_link_key {
bt_addr_t addr;
ATOMIC_DEFINE(flags, BT_LINK_KEY_NUM_FLAGS);
uint8_t val[16];
};
struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr);
struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr);
void bt_keys_link_key_clear(struct bt_keys_link_key *link_key);
#endif /* CONFIG_BLUETOOTH_BREDR */

85
net/bluetooth/keys_br.c Normal file
View file

@ -0,0 +1,85 @@
/* keys_br.c - Bluetooth BR/EDR key handling */
/*
* Copyright (c) 2015-2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <nanokernel.h>
#include <atomic.h>
#include <misc/util.h>
#include <misc/nano_work.h>
#include <bluetooth/log.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/hci.h>
#include "hci_core.h"
#include "keys.h"
#if !defined(CONFIG_BLUETOOTH_DEBUG_KEYS)
#undef BT_DBG
#define BT_DBG(fmt, ...)
#endif
static struct bt_keys_link_key key_pool[CONFIG_BLUETOOTH_MAX_PAIRED];
struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr)
{
struct bt_keys_link_key *key;
int i;
BT_DBG("%s", bt_addr_str(addr));
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
key = &key_pool[i];
if (!bt_addr_cmp(&key->addr, addr)) {
return key;
}
}
return NULL;
}
struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr)
{
struct bt_keys_link_key *key;
key = bt_keys_find_link_key(addr);
if (key) {
return key;
}
key = bt_keys_find_link_key(BT_ADDR_ANY);
if (key) {
bt_addr_copy(&key->addr, addr);
BT_DBG("created %p for %s", key, bt_addr_str(addr));
return key;
}
BT_DBG("unable to create link key for %s", bt_addr_str(addr));
return NULL;
}
void bt_keys_link_key_clear(struct bt_keys_link_key *link_key)
{
BT_DBG("%s", bt_addr_str(&link_key->addr));
memset(link_key, 0, sizeof(*link_key));
}

View file

@ -574,8 +574,8 @@ static void smp_timeout(struct nano_work *work)
* pairing failed and don't store any keys from this pairing.
*/
if (atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR) &&
smp->chan.chan.conn->keys) {
bt_keys_clear(smp->chan.chan.conn->keys, BT_KEYS_ALL);
smp->chan.chan.conn->le.keys) {
bt_keys_clear(smp->chan.chan.conn->le.keys);
}
smp_reset(smp);
@ -767,7 +767,7 @@ static uint8_t smp_send_pairing_confirm(struct bt_smp *smp)
static void legacy_distribute_keys(struct bt_smp *smp)
{
struct bt_conn *conn = smp->chan.chan.conn;
struct bt_keys *keys = conn->keys;
struct bt_keys *keys = conn->le.keys;
if (smp->local_dist & BT_SMP_DIST_ENC_KEY) {
struct bt_smp_encrypt_info *info;
@ -829,7 +829,7 @@ static void legacy_distribute_keys(struct bt_smp *smp)
static void bt_smp_distribute_keys(struct bt_smp *smp)
{
struct bt_conn *conn = smp->chan.chan.conn;
struct bt_keys *keys = conn->keys;
struct bt_keys *keys = conn->le.keys;
if (!keys) {
BT_ERR("No keys space for %s", bt_addr_le_str(&conn->le.dst));
@ -2054,8 +2054,8 @@ static uint8_t smp_pairing_failed(struct bt_smp *smp, struct net_buf *buf)
* so if there are any keys distributed, shall be cleared.
*/
if (atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR) &&
smp->chan.chan.conn->keys) {
bt_keys_clear(smp->chan.chan.conn->keys, BT_KEYS_ALL);
smp->chan.chan.conn->le.keys) {
bt_keys_clear(smp->chan.chan.conn->le.keys);
}
smp_reset(smp);
@ -2224,20 +2224,21 @@ static uint8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
auth = req->auth_req & BT_SMP_AUTH_MASK;
}
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_LTK_P256, &conn->le.dst);
if (!conn->keys) {
conn->keys = bt_keys_find(BT_KEYS_LTK, &conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, &conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK,
&conn->le.dst);
}
}
if (!conn->keys) {
if (!conn->le.keys) {
goto pair;
}
/* if MITM required key must be authenticated */
if ((auth & BT_SMP_AUTH_MITM) &&
!atomic_test_bit(conn->keys->flags, BT_KEYS_AUTHENTICATED)) {
!atomic_test_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED)) {
if (get_io_capa() != BT_SMP_IO_NO_INPUT_OUTPUT) {
BT_INFO("New auth requirements: 0x%x, repairing",
auth);
@ -2249,16 +2250,17 @@ static uint8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
goto pair;
}
/* if LE SC required and no p256 key present reapair */
if ((auth & BT_SMP_AUTH_SC) && !(conn->keys->keys & BT_KEYS_LTK_P256)) {
/* if LE SC required and no p256 key present repair */
if ((auth & BT_SMP_AUTH_SC) &&
!(conn->le.keys->keys & BT_KEYS_LTK_P256)) {
BT_INFO("New auth requirements: 0x%x, repairing", auth);
goto pair;
}
if (bt_conn_le_start_encryption(conn, conn->keys->ltk.rand,
conn->keys->ltk.ediv,
conn->keys->ltk.val,
conn->keys->enc_size) < 0) {
if (bt_conn_le_start_encryption(conn, conn->le.keys->ltk.rand,
conn->le.keys->ltk.ediv,
conn->le.keys->ltk.val,
conn->le.keys->enc_size) < 0) {
return BT_SMP_ERR_UNSPECIFIED;
}
@ -2608,7 +2610,7 @@ static void bt_smp_connected(struct bt_l2cap_chan *chan)
static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
{
struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
struct bt_keys *keys = chan->conn->keys;
struct bt_keys *keys = chan->conn->le.keys;
BT_DBG("chan %p cid 0x%04x", chan,
CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan)->tx.cid);
@ -2622,7 +2624,7 @@ static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
*/
if (!keys->keys ||
atomic_test_bit(keys->flags, BT_KEYS_DEBUG)) {
bt_keys_clear(keys, BT_KEYS_ALL);
bt_keys_clear(keys);
}
}
@ -3388,12 +3390,12 @@ void bt_smp_update_keys(struct bt_conn *conn)
* If link was successfully encrypted cleanup old keys as from now on
* only keys distributed in this pairing or LTK from LE SC will be used.
*/
if (conn->keys) {
bt_keys_clear(conn->keys, BT_KEYS_ALL);
if (conn->le.keys) {
bt_keys_clear(conn->le.keys);
}
conn->keys = bt_keys_get_addr(&conn->le.dst);
if (!conn->keys) {
conn->le.keys = bt_keys_get_addr(&conn->le.dst);
if (!conn->le.keys) {
BT_ERR("Unable to get keys for %s",
bt_addr_le_str(&conn->le.dst));
return;
@ -3401,7 +3403,7 @@ void bt_smp_update_keys(struct bt_conn *conn)
/* mark keys as debug */
if (atomic_test_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY)) {
atomic_set_bit(conn->keys->flags, BT_KEYS_DEBUG);
atomic_set_bit(conn->le.keys->flags, BT_KEYS_DEBUG);
}
/*
@ -3413,16 +3415,16 @@ void bt_smp_update_keys(struct bt_conn *conn)
case PASSKEY_DISPLAY:
case PASSKEY_INPUT:
case PASSKEY_CONFIRM:
atomic_set_bit(conn->keys->flags, BT_KEYS_AUTHENTICATED);
atomic_set_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED);
break;
case JUST_WORKS:
default:
/* unauthenticated key, clear it */
atomic_clear_bit(conn->keys->flags, BT_KEYS_AUTHENTICATED);
atomic_clear_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED);
break;
}
conn->keys->enc_size = get_encryption_key_size(smp);
conn->le.keys->enc_size = get_encryption_key_size(smp);
/*
* Store LTK if LE SC is used, this is safe since LE SC is mutually
@ -3431,11 +3433,11 @@ void bt_smp_update_keys(struct bt_conn *conn)
*/
if (atomic_test_bit(smp->flags, SMP_FLAG_SC) &&
atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
bt_keys_add_type(conn->keys, BT_KEYS_LTK_P256);
memcpy(conn->keys->ltk.val, smp->tk,
sizeof(conn->keys->ltk.val));
conn->keys->ltk.rand = 0;
conn->keys->ltk.ediv = 0;
bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
memcpy(conn->le.keys->ltk.val, smp->tk,
sizeof(conn->le.keys->ltk.val));
conn->le.keys->ltk.rand = 0;
conn->le.keys->ltk.ediv = 0;
}
}