From 6af5d1cd1f81e4e195a94dbc6f2ab513bb5400fc Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 27 Apr 2018 20:28:20 +0300 Subject: [PATCH] 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 --- subsys/bluetooth/host/conn.c | 12 ++++----- subsys/bluetooth/host/conn_internal.h | 4 +-- subsys/bluetooth/host/hci_core.c | 34 +++++++++++-------------- subsys/bluetooth/host/keys.h | 26 ++++++++----------- subsys/bluetooth/host/smp.c | 36 +++++++++++++-------------- 5 files changed, 50 insertions(+), 62 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index b99302ac715..14ce235c8ae 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -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); } diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 23b00104088..8f22e517cf9 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -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); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index d44b4b07c1c..1a13e474da6 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -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)); diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index 3d3971252f4..5d8118d6835 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -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]; }; diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index aaedd0aaec0..9a882afad64 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -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; } }