Bluetooth: SMP: Add support for H7 crypto function and CT2 auth flag
authorJohan Hedberg <johan.hedberg@intel.com>
Thu, 8 Dec 2016 06:32:54 +0000 (08:32 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 8 Dec 2016 06:50:24 +0000 (07:50 +0100)
Bluetooth 5.0 introduces a new H7 key generation function that's used
when both sides of the pairing set the CT2 authentication flag to 1.

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

index 43faf2aea2abbbd16f20a24c803a2f83dfeddc86..fae391f1871f138c802722d8d8d86d817a97947e 100644 (file)
@@ -57,7 +57,7 @@
 #define SMP_TIMEOUT    msecs_to_jiffies(30000)
 
 #define AUTH_REQ_MASK(dev)     (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
-                                0x1f : 0x07)
+                                0x3f : 0x07)
 #define KEY_DIST_MASK          0x07
 
 /* Maximum message length that can be passed to aes_cmac */
@@ -76,6 +76,7 @@ enum {
        SMP_FLAG_DHKEY_PENDING,
        SMP_FLAG_REMOTE_OOB,
        SMP_FLAG_LOCAL_OOB,
+       SMP_FLAG_CT2,
 };
 
 struct smp_dev {
@@ -357,6 +358,22 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
        return err;
 }
 
+static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16],
+                 const u8 salt[16], u8 res[16])
+{
+       int err;
+
+       SMP_DBG("w %16phN salt %16phN", w, salt);
+
+       err = aes_cmac(tfm_cmac, salt, w, 16, res);
+       if (err)
+               return err;
+
+       SMP_DBG("res %16phN", res);
+
+       return err;
+}
+
 /* The following functions map to the legacy SMP crypto functions e, c1,
  * s1 and ah.
  */
@@ -1130,20 +1147,31 @@ static void sc_add_ltk(struct smp_chan *smp)
 
 static void sc_generate_link_key(struct smp_chan *smp)
 {
-       /* These constants are as specified in the core specification.
-        * In ASCII they spell out to 'tmp1' and 'lebr'.
-        */
-       const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+       /* From core spec. Spells out in ASCII as 'lebr'. */
        const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
 
        smp->link_key = kzalloc(16, GFP_KERNEL);
        if (!smp->link_key)
                return;
 
-       if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
-               kzfree(smp->link_key);
-               smp->link_key = NULL;
-               return;
+       if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+               /* SALT = 0x00000000000000000000000000000000746D7031 */
+               const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 };
+
+               if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) {
+                       kzfree(smp->link_key);
+                       smp->link_key = NULL;
+                       return;
+               }
+       } else {
+               /* From core spec. Spells out in ASCII as 'tmp1'. */
+               const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+
+               if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
+                       kzfree(smp->link_key);
+                       smp->link_key = NULL;
+                       return;
+               }
        }
 
        if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
@@ -1169,10 +1197,7 @@ static void smp_allow_key_dist(struct smp_chan *smp)
 
 static void sc_generate_ltk(struct smp_chan *smp)
 {
-       /* These constants are as specified in the core specification.
-        * In ASCII they spell out to 'tmp2' and 'brle'.
-        */
-       const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+       /* From core spec. Spells out in ASCII as 'brle'. */
        const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
        struct hci_conn *hcon = smp->conn->hcon;
        struct hci_dev *hdev = hcon->hdev;
@@ -1187,8 +1212,19 @@ static void sc_generate_ltk(struct smp_chan *smp)
        if (key->type == HCI_LK_DEBUG_COMBINATION)
                set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
 
-       if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
-               return;
+       if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+               /* SALT = 0x00000000000000000000000000000000746D7032 */
+               const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
+
+               if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk))
+                       return;
+       } else {
+               /* From core spec. Spells out in ASCII as 'tmp2'. */
+               const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+
+               if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
+                       return;
+       }
 
        if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
                return;
@@ -1669,6 +1705,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
        if (!rsp) {
                memset(req, 0, sizeof(*req));
 
+               req->auth_req        = SMP_AUTH_CT2;
                req->init_key_dist   = local_dist;
                req->resp_key_dist   = remote_dist;
                req->max_key_size    = conn->hcon->enc_key_size;
@@ -1680,6 +1717,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
 
        memset(rsp, 0, sizeof(*rsp));
 
+       rsp->auth_req        = SMP_AUTH_CT2;
        rsp->max_key_size    = conn->hcon->enc_key_size;
        rsp->init_key_dist   = req->init_key_dist & remote_dist;
        rsp->resp_key_dist   = req->resp_key_dist & local_dist;
@@ -1744,6 +1782,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
                build_bredr_pairing_cmd(smp, req, &rsp);
 
+               if (req->auth_req & SMP_AUTH_CT2)
+                       set_bit(SMP_FLAG_CT2, &smp->flags);
+
                key_size = min(req->max_key_size, rsp.max_key_size);
                if (check_enc_key_size(conn, key_size))
                        return SMP_ENC_KEY_SIZE;
@@ -1761,9 +1802,13 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
        build_pairing_cmd(conn, req, &rsp, auth);
 
-       if (rsp.auth_req & SMP_AUTH_SC)
+       if (rsp.auth_req & SMP_AUTH_SC) {
                set_bit(SMP_FLAG_SC, &smp->flags);
 
+               if (rsp.auth_req & SMP_AUTH_CT2)
+                       set_bit(SMP_FLAG_CT2, &smp->flags);
+       }
+
        if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
                sec_level = BT_SECURITY_MEDIUM;
        else
@@ -1917,6 +1962,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
         */
        smp->remote_key_dist &= rsp->resp_key_dist;
 
+       if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2))
+               set_bit(SMP_FLAG_CT2, &smp->flags);
+
        /* For BR/EDR this means we're done and can start phase 3 */
        if (conn->hcon->type == ACL_LINK) {
                /* Clear bits which are generated but not distributed */
@@ -2312,8 +2360,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
        authreq = seclevel_to_authreq(sec_level);
 
-       if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
+       if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) {
                authreq |= SMP_AUTH_SC;
+               if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED))
+                       authreq |= SMP_AUTH_CT2;
+       }
 
        /* Require MITM if IO Capability allows or the security level
         * requires it.
index ffcc70b6b1997d3d109aeab142738a77ee31ceb9..0ff6247eaa6c0e8c19223c014d11a98d8adaee8a 100644 (file)
@@ -57,6 +57,7 @@ struct smp_cmd_pairing {
 #define SMP_AUTH_MITM          0x04
 #define SMP_AUTH_SC            0x08
 #define SMP_AUTH_KEYPRESS      0x10
+#define SMP_AUTH_CT2           0x20
 
 #define SMP_CMD_PAIRING_CONFIRM        0x03
 struct smp_cmd_pairing_confirm {