diff options
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 33 | 
1 files changed, 28 insertions, 5 deletions
| diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b53acd6c9a3d..9f77432dbe38 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1341,6 +1341,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; @@ -1358,9 +1373,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) @@ -1439,7 +1459,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; @@ -7490,7 +7513,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); @@ -7499,7 +7522,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; |