Commit 35dc6f83 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann

Bluetooth: Add key preference parameter to smp_sufficient_security

So far smp_sufficient_security() has returned false if we're encrypted
with an STK but do have an LTK available. However, for the sake of LE
CoC servers we do want to let the incoming connection through even
though we're only encrypted with the STK.

This patch adds a key preference parameter to smp_sufficient_security()
with two possible values (enum used instead of bool for readability).
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent fa37c1aa
...@@ -5391,7 +5391,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, ...@@ -5391,7 +5391,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
mutex_lock(&conn->chan_lock); mutex_lock(&conn->chan_lock);
l2cap_chan_lock(pchan); l2cap_chan_lock(pchan);
if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
SMP_ALLOW_STK)) {
result = L2CAP_CR_AUTHENTICATION; result = L2CAP_CR_AUTHENTICATION;
chan = NULL; chan = NULL;
goto response_unlock; goto response_unlock;
......
...@@ -1122,18 +1122,20 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) ...@@ -1122,18 +1122,20 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
return true; return true;
} }
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
enum smp_key_pref key_pref)
{ {
if (sec_level == BT_SECURITY_LOW) if (sec_level == BT_SECURITY_LOW)
return true; return true;
/* If we're encrypted with an STK always claim insufficient /* If we're encrypted with an STK but the caller prefers using
* security. This way we allow the connection to be re-encrypted * LTK claim insufficient security. This way we allow the
* with an LTK, even if the LTK provides the same level of * connection to be re-encrypted with an LTK, even if the LTK
* security. Only exception is if we don't have an LTK (e.g. * provides the same level of security. Only exception is if we
* because of key distribution bits). * don't have an LTK (e.g. because of key distribution bits).
*/ */
if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && if (key_pref == SMP_USE_LTK &&
test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
hcon->role)) hcon->role))
return false; return false;
...@@ -1167,7 +1169,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1167,7 +1169,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
else else
sec_level = authreq_to_seclevel(auth); sec_level = authreq_to_seclevel(auth);
if (smp_sufficient_security(hcon, sec_level)) if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
return 0; return 0;
if (sec_level > hcon->pending_sec_level) if (sec_level > hcon->pending_sec_level)
...@@ -1217,7 +1219,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) ...@@ -1217,7 +1219,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
return 1; return 1;
if (smp_sufficient_security(hcon, sec_level)) if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
return 1; return 1;
if (sec_level > hcon->pending_sec_level) if (sec_level > hcon->pending_sec_level)
......
...@@ -133,8 +133,15 @@ static inline u8 smp_ltk_sec_level(struct smp_ltk *key) ...@@ -133,8 +133,15 @@ static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
return BT_SECURITY_MEDIUM; return BT_SECURITY_MEDIUM;
} }
/* Key preferences for smp_sufficient security */
enum smp_key_pref {
SMP_ALLOW_STK,
SMP_USE_LTK,
};
/* SMP Commands */ /* SMP Commands */
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
enum smp_key_pref key_pref);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment