Bluetooth: Handle security level 4 for L2CAP connections
authorMarcel Holtmann <marcel@holtmann.org>
Thu, 16 Jan 2014 06:37:40 +0000 (22:37 -0800)
committerJohan Hedberg <johan.hedberg@intel.com>
Thu, 13 Feb 2014 07:51:35 +0000 (09:51 +0200)
With the introduction of security level 4, the L2CAP sockets need to
be made aware of this new level. This change ensures that the pairing
requirements are set correctly for these connections.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
include/net/bluetooth/l2cap.h
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c

index dbc4a89984ca67287715a8279b2d9793e7d2eebe..c695083eee2b6cce1ca7c146d5948e77736553f7 100644 (file)
@@ -91,6 +91,7 @@ struct l2cap_conninfo {
 #define L2CAP_LM_TRUSTED       0x0008
 #define L2CAP_LM_RELIABLE      0x0010
 #define L2CAP_LM_SECURE                0x0020
+#define L2CAP_LM_FIPS          0x0040
 
 /* L2CAP command codes */
 #define L2CAP_COMMAND_REJ      0x01
index b0ad2c752d738039cff8ec32c028dd109a10388b..3f0dd552cb2bc9ded817e44e794c1aa0b971e697 100644 (file)
@@ -737,6 +737,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
        case L2CAP_CHAN_RAW:
                switch (chan->sec_level) {
                case BT_SECURITY_HIGH:
+               case BT_SECURITY_FIPS:
                        return HCI_AT_DEDICATED_BONDING_MITM;
                case BT_SECURITY_MEDIUM:
                        return HCI_AT_DEDICATED_BONDING;
@@ -749,7 +750,8 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
                        if (chan->sec_level == BT_SECURITY_LOW)
                                chan->sec_level = BT_SECURITY_SDP;
                }
-               if (chan->sec_level == BT_SECURITY_HIGH)
+               if (chan->sec_level == BT_SECURITY_HIGH ||
+                   chan->sec_level == BT_SECURITY_FIPS)
                        return HCI_AT_NO_BONDING_MITM;
                else
                        return HCI_AT_NO_BONDING;
@@ -759,7 +761,8 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
                        if (chan->sec_level == BT_SECURITY_LOW)
                                chan->sec_level = BT_SECURITY_SDP;
 
-                       if (chan->sec_level == BT_SECURITY_HIGH)
+                       if (chan->sec_level == BT_SECURITY_HIGH ||
+                           chan->sec_level == BT_SECURITY_FIPS)
                                return HCI_AT_NO_BONDING_MITM;
                        else
                                return HCI_AT_NO_BONDING;
@@ -768,6 +771,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
        default:
                switch (chan->sec_level) {
                case BT_SECURITY_HIGH:
+               case BT_SECURITY_FIPS:
                        return HCI_AT_GENERAL_BONDING_MITM;
                case BT_SECURITY_MEDIUM:
                        return HCI_AT_GENERAL_BONDING;
@@ -7206,7 +7210,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
        if (encrypt == 0x00) {
                if (chan->sec_level == BT_SECURITY_MEDIUM) {
                        __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
-               } else if (chan->sec_level == BT_SECURITY_HIGH)
+               } else if (chan->sec_level == BT_SECURITY_HIGH ||
+                          chan->sec_level == BT_SECURITY_FIPS)
                        l2cap_chan_close(chan, ECONNREFUSED);
        } else {
                if (chan->sec_level == BT_SECURITY_MEDIUM)
index d58f76bcebd1e6866183360f778881f8e84d49b3..fe086b4efc0c204d18200f8599cf7cf9f0f0e8d1 100644 (file)
@@ -432,6 +432,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
                        opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
                              L2CAP_LM_SECURE;
                        break;
+               case BT_SECURITY_FIPS:
+                       opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
+                             L2CAP_LM_SECURE | L2CAP_LM_FIPS;
+                       break;
                default:
                        opt = 0;
                        break;
@@ -445,6 +449,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
                if (put_user(opt, (u32 __user *) optval))
                        err = -EFAULT;
+
                break;
 
        case L2CAP_CONNINFO:
@@ -699,6 +704,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
                        break;
                }
 
+               if (opt & L2CAP_LM_FIPS) {
+                       err = -EINVAL;
+                       break;
+               }
+
                if (opt & L2CAP_LM_AUTH)
                        chan->sec_level = BT_SECURITY_LOW;
                if (opt & L2CAP_LM_ENCRYPT)