-
Notifications
You must be signed in to change notification settings - Fork 8.1k
bluetooth: remove blocking operation in bt_conn_get_info #95600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hello @liuX10, and thank you very much for your first pull request to the Zephyr project! |
subsys/bluetooth/host/keys.h
Outdated
struct bt_keys_link_key { | ||
bt_addr_t addr; | ||
uint8_t storage_start[0] __aligned(sizeof(void *)); | ||
uint8_t key_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong, but wouldn't this affect BT_KEYS_LINK_KEY_STORAGE_LEN
, and thus this change would basically invalidate/break any currently stored keys in persistent storage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Thalley Yes, you are right.
With the changes in this PR, the key size does not need to be stored in persistent storage, as it is only used to store the encrypted key size.
While, for the follow-up, if there is a scenario where the previously encrypted key size needs to be used, we will also encounter the situation where BT_KEYS_LINK_KEY_STORAGE_LEN
is modified. For this case, how it is processed in Zephyr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the changes in this PR, the key size does not need to be stored in persistent storage, as it is only used to store the encrypted key size.
In that case, I think the key_size
should be moved above storage_start
While, for the follow-up, if there is a scenario where the previously encrypted key size needs to be used, we will also encounter the situation where BT_KEYS_LINK_KEY_STORAGE_LEN is modified. For this case, how it is processed in Zephyr?
Not sure I follow this - Can you elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, moving key_size
above storage_start
can prevent decoding errors when load stored keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@liuX10 This also means that we don't store the key_size
in flash.
When we re-read the keys, then we won't know the size of the key:
memcpy(link_key->storage_start, val, len);
LOG_DBG("Successfully restored link key for %s", bt_addr_le_str(&le_addr));
But I think this is also an issue today, so perhaps that needs to be followed up with another PR?
In comparison, have a look at the BT LE keys:
struct bt_keys {
uint8_t id;
bt_addr_le_t addr;
uint8_t state;
uint8_t storage_start[0] __aligned(sizeof(void *));
uint8_t enc_size;
uint8_t flags;
uint16_t keys;
struct bt_ltk ltk;
struct bt_irk irk;
#if defined(CONFIG_BT_SIGNING)
struct bt_csrk local_csrk;
struct bt_csrk remote_csrk;
#endif /* BT_SIGNING */
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
struct bt_ltk periph_ltk;
#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
#if (defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST))
uint32_t aging_counter;
#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
};
Here the enc_size
is part of what we store in flash (defined after storage_start
), so when we restore the keys from flash, we know the actual size of the key.
So I think you need to put key_size
after storage_start
to support this correctly, but that will, as my original comment pointed out, probably invalidate all existing BT Classic settings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link key is always 128bits. And the encryption key size is negotiated. And the range is 8bits ~ 128 bits. So the encryption key size only can be got when ACL connection is established.
I think the enc_key_size is 0 when calling get_info
, if the ACL is not encrypted. And if the encrypt changed or key refreshed event notified, the enc key size can be got from HCI_Encryption_Change[v2]
or HCI_Read_Encryption_Key_Size
. And it is kept into struct bt_keys::enc_size
.
And the enc_key_size is struct bt_keys::enc_size
when calling get_info
if the ACL is encrypted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link key is always 128bits. And the encryption key size is negotiated. And the range is 8bits ~ 128 bits. So the encryption key size only can be got when ACL connection is established.
Ah, given the naming, I thought bt_keys_link_key.key_size
referred to the link key size, but it sounds like it refers to the encryption key size (which makes sense). If the link key size is always 128 bits, then I think everything here makes sense :) But perhaps bt_keys_link_key.key_size
should be updated to enc_key_size
to avoid confusion (for people like me who are not experts in BT Classic) - Perhaps with an additional comment that the key size will be updated once the link is encrypted, and is otherwise 0.
One followup question: With the same link key, can the encryption key size change between connections? i.e. can the following happen:
- Connect 2 devices. Encryption key size is 80 bits.
- Devices disconnect
- Connect the same 2 devices. Encryption key size is 88 bits
Just wondering if conn->br.link_key->key_size
should be set to 0
on disconnect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps with an additional comment that the key size will be updated once the link is encrypted, and is otherwise 0.
Yes, I think so.
- Connect 2 devices. Encryption key size is 80 bits.
- Devices disconnect
- Connect the same 2 devices. Encryption key size is 88 bits
I did not notice that. I think it depends on the implementation of controller.
Just wondering if
conn->br.link_key->key_size
should be set to0
on disconnect
Yes, I think it is reasonable.
@liuX10 Could you please update the PR to address these comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like we are in agreement
So add comment/rename to make it clear that it is the size of the encryption key, and not the link key, and reset the encryption key size to 0 on disconnect, as it may change between connections, and storing the encryption key size from the last connection may be confusing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay! so I need to rename key_size as enc_key_size, and reset enc_key_size to 0 as disconnect.
subsys/bluetooth/host/hci_core.c
Outdated
* database row for this connection. | ||
*/ | ||
if (conn->type == BT_CONN_TYPE_BR && conn->br.link_key != NULL && | ||
atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Thalley I found that there is an additional condition in this conditional statement that may prevent enc_key_size
from being set to 0.
atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, my understanding from #95600 (comment) was that the encryption key size could be different between connections, even when we are bonded.
i.e. even if we are bonded, we should set the encryption key size to 0, which the current patch you just pushed seemingly doesn't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Thalley I guess you might have misunderstood the meaning of BT_CONN_BR_NOBOND
. This flag means pair but not bond.
Previous changes may exist. In bond mode, enc_key_size
is not reset to 0 as disconnect; it is only set to 0 in not bond mode alongside Linkkey clear
.
if (conn->type == BT_CONN_TYPE_BR && conn->br.link_key != NULL &&
atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND))
now, current push ensures that the reset of enc_key_size
is no longer tied to BOND mode or non-BOND mode.
if (conn->type == BT_CONN_TYPE_BR && conn->br.link_key != NULL) {
if (atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND))
bt_keys_link_key_clear(conn->br.link_key);
conn->br.link_key->enc_key_size = 0;
}
@liuX10 you still need to fix the Compliance check. It seems like the git author doesn't match the signed-off-by line. You should be able to fix that with |
Hi! @jhedberg |
@lylezhu2012 can also approve as the assignee :) |
@liuX10 there's a Compliance check failure that still needs fixing |
1d09429
to
4f60807
Compare
bt_conn_get_info API is used to retrieve connection-related information. However, bt_conn_get_info sends the HCI command BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE to retrieve current key_size, causing excessive blocking time. Signed-off-by: Xiang Liu <[email protected]>
|
Hi @liuX10! To celebrate this milestone and showcase your contribution, we'd love to award you the Zephyr Technical Contributor badge. If you're interested, please claim your badge by filling out this form: Claim Your Zephyr Badge. Thank you for your valuable input, and we look forward to seeing more of your contributions in the future! 🪁 |
bt_conn_get_info API is used to retrieve connection-related information. However, bt_conn_get_info sends the HCI command BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE to retrieve current key_size, causing excessive blocking time.