Bluetooth: Compress bt_keys struct

There's a bit of unnecessary space in the bt_keys struct. Re-design
some fields for a more compact format, which is particularly helpful
now that the struct gets stored as-is to flash through the settings
API.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-04-27 20:28:20 +03:00 committed by Anas Nashif
commit 6af5d1cd1f
5 changed files with 50 additions and 62 deletions

View file

@ -785,8 +785,8 @@ void bt_conn_identity_resolved(struct bt_conn *conn)
}
}
int bt_conn_le_start_encryption(struct bt_conn *conn, u64_t rand,
u16_t ediv, const u8_t *ltk, size_t len)
int bt_conn_le_start_encryption(struct bt_conn *conn, u8_t rand[8], u16_t ediv,
const u8_t *ltk, size_t len)
{
struct bt_hci_cp_le_start_encryption *cp;
struct net_buf *buf;
@ -798,7 +798,7 @@ int bt_conn_le_start_encryption(struct bt_conn *conn, u64_t rand,
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->rand = rand;
memcpy(&cp->rand, rand, sizeof(cp->rand));
cp->ediv = ediv;
memcpy(cp->ltk, ltk, len);
@ -906,14 +906,12 @@ static int start_security(struct bt_conn *conn)
}
if (conn->required_sec_level > BT_SECURITY_MEDIUM &&
!atomic_test_bit(conn->le.keys->flags,
BT_KEYS_AUTHENTICATED)) {
!(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->le.keys->flags,
BT_KEYS_AUTHENTICATED) &&
!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
!(conn->le.keys->keys & BT_KEYS_LTK_P256)) {
return bt_smp_send_pairing_req(conn);
}

View file

@ -194,8 +194,8 @@ bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
#if defined(CONFIG_BT_SMP)
/* rand and ediv should be in BT order */
int bt_conn_le_start_encryption(struct bt_conn *conn, u64_t rand,
u16_t ediv, const u8_t *ltk, size_t len);
int bt_conn_le_start_encryption(struct bt_conn *conn, u8_t rand[8], u16_t ediv,
const u8_t *ltk, size_t len);
/* Notify higher layers that RPA was resolved */
void bt_conn_identity_resolved(struct bt_conn *conn);

View file

@ -732,12 +732,14 @@ static void update_conn_param(struct bt_conn *conn)
#if defined(CONFIG_BT_SMP)
static void update_pending_id(struct bt_keys *keys)
{
if (atomic_test_and_clear_bit(keys->flags, BT_KEYS_ID_PENDING_ADD)) {
if (keys->flags & BT_KEYS_ID_PENDING_ADD) {
keys->flags &= ~BT_KEYS_ID_PENDING_ADD;
bt_id_add(keys);
return;
}
if (atomic_test_and_clear_bit(keys->flags, BT_KEYS_ID_PENDING_DEL)) {
if (keys->flags & BT_KEYS_ID_PENDING_DEL) {
keys->flags &= ~BT_KEYS_ID_PENDING_DEL;
bt_id_del(keys);
return;
}
@ -1459,8 +1461,7 @@ static void update_sec_level_br(struct bt_conn *conn)
}
if (conn->br.link_key) {
if (atomic_test_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED)) {
if (conn->br.link_key->flags & BT_LINK_KEY_AUTHENTICATED) {
if (conn->encrypt == 0x02) {
conn->sec_level = BT_SECURITY_FIPS;
} else {
@ -1587,7 +1588,7 @@ static void link_key_notify(struct net_buf *buf)
}
/* clear any old Link Key flags */
atomic_set(conn->br.link_key->flags, 0);
conn->br.link_key->flags = 0;
switch (evt->key_type) {
case BT_LK_COMBINATION:
@ -1597,14 +1598,12 @@ 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->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED);
conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
}
memcpy(conn->br.link_key->val, evt->link_key, 16);
break;
case BT_LK_AUTH_COMBINATION_P192:
atomic_set_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED);
conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
/* fall through */
case BT_LK_UNAUTH_COMBINATION_P192:
/* Mark no-bond so that link-key is removed on disconnection */
@ -1615,11 +1614,10 @@ static void link_key_notify(struct net_buf *buf)
memcpy(conn->br.link_key->val, evt->link_key, 16);
break;
case BT_LK_AUTH_COMBINATION_P256:
atomic_set_bit(conn->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED);
conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
/* fall through */
case BT_LK_UNAUTH_COMBINATION_P256:
atomic_set_bit(conn->br.link_key->flags, BT_LINK_KEY_SC);
conn->br.link_key->flags |= BT_LINK_KEY_SC;
/* Mark no-bond so that link-key is removed on disconnection */
if (bt_conn_ssp_get_auth(conn) < BT_HCI_DEDICATED_BONDING) {
@ -1703,8 +1701,7 @@ 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->br.link_key->flags,
BT_LINK_KEY_AUTHENTICATED) &&
if (!(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);
@ -2431,7 +2428,7 @@ int bt_id_add(struct bt_keys *keys)
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (conn) {
atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING);
atomic_set_bit(keys->flags, BT_KEYS_ID_PENDING_ADD);
keys->flags |= BT_KEYS_ID_PENDING_ADD;
bt_conn_unref(conn);
return -EAGAIN;
}
@ -2533,7 +2530,7 @@ int bt_id_del(struct bt_keys *keys)
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (conn) {
atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING);
atomic_set_bit(keys->flags, BT_KEYS_ID_PENDING_DEL);
keys->flags |= BT_KEYS_ID_PENDING_DEL;
bt_conn_unref(conn);
return -EAGAIN;
}
@ -2603,8 +2600,7 @@ static void update_sec_level(struct bt_conn *conn)
return;
}
if (conn->le.keys && atomic_test_bit(conn->le.keys->flags,
BT_KEYS_AUTHENTICATED)) {
if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
if (conn->le.keys->keys & BT_KEYS_LTK_P256) {
conn->sec_level = BT_SECURITY_FIPS;
} else {
@ -2833,7 +2829,7 @@ static void le_ltk_request(struct net_buf *buf)
#if !defined(CONFIG_BT_SMP_SC_ONLY)
if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) &&
conn->le.keys->slave_ltk.rand == evt->rand &&
!memcmp(conn->le.keys->slave_ltk.rand, &evt->rand, 8) &&
conn->le.keys->slave_ltk.ediv == evt->ediv) {
buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY,
sizeof(*cp));

View file

@ -20,17 +20,14 @@ enum {
};
enum {
BT_KEYS_AUTHENTICATED,
BT_KEYS_DEBUG,
BT_KEYS_ID_PENDING_ADD,
BT_KEYS_ID_PENDING_DEL,
/* Total number of flags - must be at the end of the enum */
BT_KEYS_NUM_FLAGS,
BT_KEYS_AUTHENTICATED = BIT(0),
BT_KEYS_DEBUG = BIT(1),
BT_KEYS_ID_PENDING_ADD = BIT(2),
BT_KEYS_ID_PENDING_DEL = BIT(3),
};
struct bt_ltk {
u64_t rand;
u8_t rand[8];
u16_t ediv;
u8_t val[16];
};
@ -49,7 +46,7 @@ struct bt_keys {
bt_addr_le_t addr;
u8_t storage_start[0];
u8_t enc_size;
ATOMIC_DEFINE(flags, BT_KEYS_NUM_FLAGS);
u8_t flags;
u16_t keys;
struct bt_ltk ltk;
struct bt_irk irk;
@ -88,17 +85,14 @@ static inline int bt_keys_store(struct bt_keys *keys)
#endif
enum {
BT_LINK_KEY_AUTHENTICATED,
BT_LINK_KEY_DEBUG,
BT_LINK_KEY_SC,
/* Total number of flags - must be at the end of the enum */
BT_LINK_KEY_NUM_FLAGS,
BT_LINK_KEY_AUTHENTICATED = BIT(0),
BT_LINK_KEY_DEBUG = BIT(1),
BT_LINK_KEY_SC = BIT(2),
};
struct bt_keys_link_key {
bt_addr_t addr;
ATOMIC_DEFINE(flags, BT_LINK_KEY_NUM_FLAGS);
u8_t flags;
u8_t val[16];
};

View file

@ -673,12 +673,12 @@ static void sc_derive_link_key(struct bt_smp *smp)
bt_keys_link_key_clear(link_key);
}
atomic_set_bit(link_key->flags, BT_LINK_KEY_SC);
link_key->flags |= BT_LINK_KEY_SC;
if (atomic_test_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED)) {
atomic_set_bit(link_key->flags, BT_LINK_KEY_AUTHENTICATED);
if (conn->le.keys->flags & BT_KEYS_AUTHENTICATED) {
link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
} else {
atomic_clear_bit(link_key->flags, BT_LINK_KEY_AUTHENTICATED);
link_key->flags &= ~BT_LINK_KEY_AUTHENTICATED;
}
}
@ -836,13 +836,13 @@ static void smp_br_derive_ltk(struct bt_smp_br *smp)
}
keys->ltk.ediv = 0;
keys->ltk.rand = 0;
memset(keys->ltk.rand, 0, sizeof(keys->ltk.rand));
keys->enc_size = smp->enc_key_size;
if (atomic_test_bit(link_key->flags, BT_LINK_KEY_AUTHENTICATED)) {
atomic_set_bit(keys->flags, BT_KEYS_AUTHENTICATED);
if (link_key->flags & BT_LINK_KEY_AUTHENTICATED) {
keys->flags |= BT_KEYS_AUTHENTICATED;
} else {
atomic_clear_bit(keys->flags, BT_KEYS_AUTHENTICATED);
keys->flags &= ~BT_KEYS_AUTHENTICATED;
}
BT_DBG("LTK derived from LinkKey");
@ -1719,7 +1719,7 @@ static void legacy_distribute_keys(struct bt_smp *smp)
memcpy(keys->slave_ltk.val, key,
sizeof(keys->slave_ltk.val));
keys->slave_ltk.rand = rand;
memcpy(keys->slave_ltk.rand, &rand, sizeof(rand));
keys->slave_ltk.ediv = ediv;
}
}
@ -1886,7 +1886,7 @@ static u8_t legacy_request_tk(struct bt_smp *smp)
* keys with unauthenticated ones.
*/
keys = bt_keys_find_addr(&conn->le.dst);
if (keys && atomic_test_bit(keys->flags, BT_KEYS_AUTHENTICATED) &&
if (keys && (keys->flags & BT_KEYS_AUTHENTICATED) &&
smp->method == JUST_WORKS) {
BT_ERR("JustWorks failed, authenticated keys present");
return BT_SMP_ERR_UNSPECIFIED;
@ -2124,7 +2124,7 @@ static u8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf)
}
keys->ltk.ediv = req->ediv;
keys->ltk.rand = req->rand;
memcpy(keys->ltk.rand, &req->rand, sizeof(req->rand));
smp->remote_dist &= ~BT_SMP_DIST_ENC_KEY;
}
@ -3141,7 +3141,7 @@ static u8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
/* if MITM required key must be authenticated */
if ((auth & BT_SMP_AUTH_MITM) &&
!atomic_test_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED)) {
!(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);
@ -3529,8 +3529,7 @@ static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
* If debug keys were used for pairing remove them.
* No keys indicate no bonding so free keys storage.
*/
if (!keys->keys ||
atomic_test_bit(keys->flags, BT_KEYS_DEBUG)) {
if (!keys->keys || (keys->flags & BT_KEYS_DEBUG)) {
bt_keys_clear(keys);
}
}
@ -4350,7 +4349,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->le.keys->flags, BT_KEYS_DEBUG);
conn->le.keys->flags |= BT_KEYS_DEBUG;
}
/*
@ -4362,12 +4361,12 @@ void bt_smp_update_keys(struct bt_conn *conn)
case PASSKEY_DISPLAY:
case PASSKEY_INPUT:
case PASSKEY_CONFIRM:
atomic_set_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED);
conn->le.keys->flags |= BT_KEYS_AUTHENTICATED;
break;
case JUST_WORKS:
default:
/* unauthenticated key, clear it */
atomic_clear_bit(conn->le.keys->flags, BT_KEYS_AUTHENTICATED);
conn->le.keys->flags &= ~BT_KEYS_AUTHENTICATED;
break;
}
@ -4383,7 +4382,8 @@ void bt_smp_update_keys(struct bt_conn *conn)
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;
memset(conn->le.keys->ltk.rand, 0,
sizeof(conn->le.keys->ltk.rand));
conn->le.keys->ltk.ediv = 0;
}
}