Bluetooth: Add key preference parameter to smp_sufficient_security
authorJohan Hedberg <johan.hedberg@intel.com>
Thu, 13 Nov 2014 08:55:18 +0000 (10:55 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 15 Nov 2014 00:46:49 +0000 (01:46 +0100)
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: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/l2cap_core.c
net/bluetooth/smp.c
net/bluetooth/smp.h

index 76045497eaa144a154851069bcfcd18d340b9444..a37f809591adc5d0b35fe9997e84d44adff81776 100644 (file)
@@ -5391,7 +5391,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
        mutex_lock(&conn->chan_lock);
        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;
                chan = NULL;
                goto response_unlock;
index 3b63c7f09dd5edc28ac774e34422e00cc01856ce..3dc5f0e66405c580bfa83b870353492cf3dade17 100644 (file)
@@ -1122,18 +1122,20 @@ static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
        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)
                return true;
 
-       /* If we're encrypted with an STK always claim insufficient
-        * security. This way we allow the connection to be re-encrypted
-        * with an LTK, even if the LTK provides the same level of
-        * security. Only exception is if we don't have an LTK (e.g.
-        * because of key distribution bits).
+       /* If we're encrypted with an STK but the caller prefers using
+        * LTK claim insufficient security. This way we allow the
+        * connection to be re-encrypted with an LTK, even if the LTK
+        * provides the same level of security. Only exception is if we
+        * 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,
                                 hcon->role))
                return false;
@@ -1167,7 +1169,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        else
                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;
 
        if (sec_level > hcon->pending_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))
                return 1;
 
-       if (smp_sufficient_security(hcon, sec_level))
+       if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
                return 1;
 
        if (sec_level > hcon->pending_sec_level)
index 86a683a8b4917fe7ba0567254da8da210909f13c..f76083b8500535395ee5c063aa609bcc5e69d1cd 100644 (file)
@@ -133,8 +133,15 @@ static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
        return BT_SECURITY_MEDIUM;
 }
 
+/* Key preferences for smp_sufficient security */
+enum smp_key_pref {
+       SMP_ALLOW_STK,
+       SMP_USE_LTK,
+};
+
 /* 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_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);