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:
parent
709111b813
commit
60691c4650
8 changed files with 253 additions and 237 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
85
net/bluetooth/keys_br.c
Normal 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));
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue