|
|
@@ -1340,6 +1340,21 @@ static void l2cap_request_info(struct l2cap_conn *conn)
|
|
|
sizeof(req), &req);
|
|
|
}
|
|
|
|
|
|
+static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
|
|
|
+{
|
|
|
+ /* The minimum encryption key size needs to be enforced by the
|
|
|
+ * host stack before establishing any L2CAP connections. The
|
|
|
+ * specification in theory allows a minimum of 1, but to align
|
|
|
+ * BR/EDR and LE transports, a minimum of 7 is chosen.
|
|
|
+ *
|
|
|
+ * This check might also be called for unencrypted connections
|
|
|
+ * that have no key size requirements. Ensure that the link is
|
|
|
+ * actually encrypted before enforcing a key size.
|
|
|
+ */
|
|
|
+ return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
|
|
|
+ hcon->enc_key_size > HCI_MIN_ENC_KEY_SIZE);
|
|
|
+}
|
|
|
+
|
|
|
static void l2cap_do_start(struct l2cap_chan *chan)
|
|
|
{
|
|
|
struct l2cap_conn *conn = chan->conn;
|
|
|
@@ -1357,9 +1372,14 @@ static void l2cap_do_start(struct l2cap_chan *chan)
|
|
|
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
|
|
|
return;
|
|
|
|
|
|
- if (l2cap_chan_check_security(chan, true) &&
|
|
|
- __l2cap_no_conn_pending(chan))
|
|
|
+ if (!l2cap_chan_check_security(chan, true) ||
|
|
|
+ !__l2cap_no_conn_pending(chan))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (l2cap_check_enc_key_size(conn->hcon))
|
|
|
l2cap_start_connection(chan);
|
|
|
+ else
|
|
|
+ __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
|
|
|
}
|
|
|
|
|
|
static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
|
|
|
@@ -1438,7 +1458,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- l2cap_start_connection(chan);
|
|
|
+ if (l2cap_check_enc_key_size(conn->hcon))
|
|
|
+ l2cap_start_connection(chan);
|
|
|
+ else
|
|
|
+ l2cap_chan_close(chan, ECONNREFUSED);
|
|
|
|
|
|
} else if (chan->state == BT_CONNECT2) {
|
|
|
struct l2cap_conn_rsp rsp;
|
|
|
@@ -7455,7 +7478,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|
|
}
|
|
|
|
|
|
if (chan->state == BT_CONNECT) {
|
|
|
- if (!status)
|
|
|
+ if (!status && l2cap_check_enc_key_size(hcon))
|
|
|
l2cap_start_connection(chan);
|
|
|
else
|
|
|
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
|
|
|
@@ -7464,7 +7487,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|
|
struct l2cap_conn_rsp rsp;
|
|
|
__u16 res, stat;
|
|
|
|
|
|
- if (!status) {
|
|
|
+ if (!status && l2cap_check_enc_key_size(hcon)) {
|
|
|
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
|
|
|
res = L2CAP_CR_PEND;
|
|
|
stat = L2CAP_CS_AUTHOR_PEND;
|