[PATCH v2] Bluetooth: Add more enc key size check

From: Alex Lu
Date: Mon Dec 11 2023 - 04:29:47 EST


From: Alex Lu <alex_lu@xxxxxxxxxxxxxx>

When we are slave role and receives l2cap conn req when encryption has
started, we should check the enc key size to avoid KNOB attack or BLUFFS
attack.
>From SIG recommendation, implementations are advised to reject
service-level connections on an encrypted baseband link with key
strengths below 7 octets.

The btmon log below shows the case that lacks enc key size check.

> HCI Event: Connect Request (0x04) plen 10
Address: BB:22:33:44:55:99 (OUI BB-22-33)
Class: 0x480104
Major class: Computer (desktop, notebook, PDA, organizers)
Minor class: Desktop workstation
Capturing (Scanner, Microphone)
Telephony (Cordless telephony, Modem, Headset)
Link type: ACL (0x01)
< HCI Command: Accept Connection Request (0x01|0x0009) plen 7
Address: BB:22:33:44:55:99 (OUI BB-22-33)
Role: Peripheral (0x01)
> HCI Event: Command Status (0x0f) plen 4
Accept Connection Request (0x01|0x0009) ncmd 2
Status: Success (0x00)
> HCI Event: Connect Complete (0x03) plen 11
Status: Success (0x00)
Handle: 1
Address: BB:22:33:44:55:99 (OUI BB-22-33)
Link type: ACL (0x01)
Encryption: Disabled (0x00)
...

> HCI Event: Encryption Change (0x08) plen 4
Status: Success (0x00)
Handle: 1 Address: BB:22:33:44:55:99 (OUI BB-22-33)
Encryption: Enabled with E0 (0x01)
< HCI Command: Read Encryption Key Size (0x05|0x0008) plen 2
Handle: 1 Address: BB:22:33:44:55:99 (OUI BB-22-33)
> HCI Event: Command Complete (0x0e) plen 7
Read Encryption Key Size (0x05|0x0008) ncmd 2
Status: Success (0x00)
Handle: 1 Address: BB:22:33:44:55:99 (OUI BB-22-33)
Key size: 6
...

// We should check the enc key size
> ACL Data RX: Handle 1 flags 0x02 dlen 12
L2CAP: Connection Request (0x02) ident 3 len 4
PSM: 25 (0x0019)
Source CID: 64
< ACL Data TX: Handle 1 flags 0x00 dlen 16
L2CAP: Connection Response (0x03) ident 3 len 8
Destination CID: 64
Source CID: 64
Result: Connection pending (0x0001)
Status: Authorization pending (0x0002)
> HCI Event: Number of Completed Packets (0x13) plen 5
Num handles: 1
Handle: 1 Address: BB:22:33:44:55:99 (OUI BB-22-33)
Count: 1
#35: len 16 (25 Kb/s)
Latency: 5 msec (2-7 msec ~4 msec)
< ACL Data TX: Handle 1 flags 0x00 dlen 16
L2CAP: Connection Response (0x03) ident 3 len 8
Destination CID: 64
Source CID: 64
Result: Connection successful (0x0000)
Status: No further information available (0x0000)

Signed-off-by: Alex Lu <alex_lu@xxxxxxxxxxxxxx>
Signed-off-by: Max Chou <max.chou@xxxxxxxxxxx>
---
Changes in v2:
- Fix compiling issue reported by sparse

net/bluetooth/l2cap_core.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 17ca13e8c044..a9809fbe6b00 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1669,7 +1669,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp.dcid = cpu_to_le16(chan->scid);

if (l2cap_chan_check_security(chan, false)) {
- if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
+ if (!l2cap_check_enc_key_size(conn->hcon)) {
+ l2cap_state_change(chan, BT_DISCONN);
+ __set_chan_timer(chan,
+ L2CAP_DISC_TIMEOUT);
+ rsp.result = cpu_to_le16(L2CAP_CR_SEC_BLOCK);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+ } else if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
chan->ops->defer(chan);
@@ -4202,7 +4208,15 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,

if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_chan_check_security(chan, false)) {
- if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
+ /* As slave role, we should check the enc key size when
+ * l2cap conn req is received.
+ */
+ if (!l2cap_check_enc_key_size(conn->hcon)) {
+ l2cap_state_change(chan, BT_DISCONN);
+ __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
+ result = L2CAP_CR_SEC_BLOCK;
+ status = L2CAP_CS_NO_INFO;
+ } else if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHOR_PEND;
--
2.39.2