Bluetooth: Fix error returns for Read Local OOB Extended Data commands
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / smp.c
index d6ef7e48c2c3918a821ea05ce2f450ee7912cbde..1ec3f66b5a74ec1027efa078409cfbcf88e18c73 100644 (file)
@@ -52,7 +52,7 @@
 
 #define SMP_TIMEOUT    msecs_to_jiffies(30000)
 
-#define AUTH_REQ_MASK(dev)     (test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \
+#define AUTH_REQ_MASK(dev)     (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
                                 0x1f : 0x07)
 #define KEY_DIST_MASK          0x07
 
@@ -70,7 +70,19 @@ enum {
        SMP_FLAG_DEBUG_KEY,
        SMP_FLAG_WAIT_USER,
        SMP_FLAG_DHKEY_PENDING,
-       SMP_FLAG_OOB,
+       SMP_FLAG_REMOTE_OOB,
+       SMP_FLAG_LOCAL_OOB,
+};
+
+struct smp_dev {
+       /* Secure Connections OOB data */
+       u8                      local_pk[64];
+       u8                      local_sk[32];
+       u8                      local_rand[16];
+       bool                    debug_key;
+
+       struct crypto_blkcipher *tfm_aes;
+       struct crypto_hash      *tfm_cmac;
 };
 
 struct smp_chan {
@@ -84,7 +96,8 @@ struct smp_chan {
        u8              rrnd[16]; /* SMP Pairing Random (remote) */
        u8              pcnf[16]; /* SMP Pairing Confirm */
        u8              tk[16]; /* SMP Temporary Key */
-       u8              rr[16];
+       u8              rr[16]; /* Remote OOB ra/rb value */
+       u8              lr[16]; /* Local OOB ra/rb value */
        u8              enc_key_size;
        u8              remote_key_dist;
        bdaddr_t        id_addr;
@@ -478,18 +491,18 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
                     const bdaddr_t *bdaddr)
 {
        struct l2cap_chan *chan = hdev->smp_data;
-       struct crypto_blkcipher *tfm;
+       struct smp_dev *smp;
        u8 hash[3];
        int err;
 
        if (!chan || !chan->data)
                return false;
 
-       tfm = chan->data;
+       smp = chan->data;
 
        BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
 
-       err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
+       err = smp_ah(smp->tfm_aes, irk, &bdaddr->b[3], hash);
        if (err)
                return false;
 
@@ -499,20 +512,20 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
 int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
 {
        struct l2cap_chan *chan = hdev->smp_data;
-       struct crypto_blkcipher *tfm;
+       struct smp_dev *smp;
        int err;
 
        if (!chan || !chan->data)
                return -EOPNOTSUPP;
 
-       tfm = chan->data;
+       smp = chan->data;
 
        get_random_bytes(&rpa->b[3], 3);
 
        rpa->b[5] &= 0x3f;      /* Clear two most significant bits */
        rpa->b[5] |= 0x40;      /* Set second most significant bit */
 
-       err = smp_ah(tfm, irk, &rpa->b[3], rpa->b);
+       err = smp_ah(smp->tfm_aes, irk, &rpa->b[3], rpa->b);
        if (err < 0)
                return err;
 
@@ -521,6 +534,53 @@ int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
        return 0;
 }
 
+int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
+{
+       struct l2cap_chan *chan = hdev->smp_data;
+       struct smp_dev *smp;
+       int err;
+
+       if (!chan || !chan->data)
+               return -EOPNOTSUPP;
+
+       smp = chan->data;
+
+       if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
+               BT_DBG("Using debug keys");
+               memcpy(smp->local_pk, debug_pk, 64);
+               memcpy(smp->local_sk, debug_sk, 32);
+               smp->debug_key = true;
+       } else {
+               while (true) {
+                       /* Generate local key pair for Secure Connections */
+                       if (!ecc_make_key(smp->local_pk, smp->local_sk))
+                               return -EIO;
+
+                       /* This is unlikely, but we need to check that
+                        * we didn't accidentially generate a debug key.
+                        */
+                       if (memcmp(smp->local_sk, debug_sk, 32))
+                               break;
+               }
+               smp->debug_key = false;
+       }
+
+       SMP_DBG("OOB Public Key X: %32phN", smp->local_pk);
+       SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32);
+       SMP_DBG("OOB Private Key:  %32phN", smp->local_sk);
+
+       get_random_bytes(smp->local_rand, 16);
+
+       err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk,
+                    smp->local_rand, 0, hash);
+       if (err < 0)
+               return err;
+
+       memcpy(rand, smp->local_rand, 16);
+
+       return 0;
+}
+
 static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
        struct l2cap_chan *chan = conn->smp;
@@ -589,7 +649,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
        struct hci_dev *hdev = hcon->hdev;
        u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
 
-       if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) {
+       if (hci_dev_test_flag(hdev, HCI_BONDABLE)) {
                local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
                remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
                authreq |= SMP_AUTH_BONDING;
@@ -597,18 +657,18 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                authreq &= ~SMP_AUTH_BONDING;
        }
 
-       if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
+       if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING))
                remote_dist |= SMP_DIST_ID_KEY;
 
-       if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
+       if (hci_dev_test_flag(hdev, HCI_PRIVACY))
                local_dist |= SMP_DIST_ID_KEY;
 
-       if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+       if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
            (authreq & SMP_AUTH_SC)) {
                struct oob_data *oob_data;
                u8 bdaddr_type;
 
-               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+               if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
                        local_dist |= SMP_DIST_LINK_KEY;
                        remote_dist |= SMP_DIST_LINK_KEY;
                }
@@ -621,10 +681,12 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
                                                    bdaddr_type);
                if (oob_data && oob_data->present) {
-                       set_bit(SMP_FLAG_OOB, &smp->flags);
+                       set_bit(SMP_FLAG_REMOTE_OOB, &smp->flags);
                        oob_flag = SMP_OOB_PRESENT;
                        memcpy(smp->rr, oob_data->rand256, 16);
                        memcpy(smp->pcnf, oob_data->hash256, 16);
+                       SMP_DBG("OOB Remote Confirmation: %16phN", smp->pcnf);
+                       SMP_DBG("OOB Remote Random: %16phN", smp->rr);
                }
 
        } else {
@@ -681,9 +743,9 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
        complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
        mgmt_smp_complete(hcon, complete);
 
-       kfree(smp->csrk);
-       kfree(smp->slave_csrk);
-       kfree(smp->link_key);
+       kzfree(smp->csrk);
+       kzfree(smp->slave_csrk);
+       kzfree(smp->link_key);
 
        crypto_free_blkcipher(smp->tfm_aes);
        crypto_free_hash(smp->tfm_cmac);
@@ -692,7 +754,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
         * support hasn't been explicitly enabled.
         */
        if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
-           !test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) {
+           !hci_dev_test_flag(hcon->hdev, HCI_KEEP_DEBUG_KEYS)) {
                list_del_rcu(&smp->ltk->list);
                kfree_rcu(smp->ltk, rcu);
                smp->ltk = NULL;
@@ -717,7 +779,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
        }
 
        chan->data = NULL;
-       kfree(smp);
+       kzfree(smp);
        hci_conn_drop(hcon);
 }
 
@@ -818,6 +880,12 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
                return 0;
        }
 
+       /* If this function is used for SC -> legacy fallback we
+        * can only recover the just-works case.
+        */
+       if (test_bit(SMP_FLAG_SC, &smp->flags))
+               return -EINVAL;
+
        /* Not Just Works/Confirm results in MITM Authentication */
        if (smp->method != JUST_CFM) {
                set_bit(SMP_FLAG_MITM_AUTH, &smp->flags);
@@ -1052,7 +1120,7 @@ static void smp_notify_keys(struct l2cap_conn *conn)
                        /* Don't keep debug keys around if the relevant
                         * flag is not set.
                         */
-                       if (!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags) &&
+                       if (!hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS) &&
                            key->type == HCI_LK_DEBUG_COMBINATION) {
                                list_del_rcu(&key->list);
                                kfree_rcu(key, rcu);
@@ -1097,13 +1165,13 @@ static void sc_generate_link_key(struct smp_chan *smp)
                return;
 
        if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
-               kfree(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)) {
-               kfree(smp->link_key);
+               kzfree(smp->link_key);
                smp->link_key = NULL;
                return;
        }
@@ -1300,7 +1368,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
        smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(smp->tfm_aes)) {
                BT_ERR("Unable to create ECB crypto context");
-               kfree(smp);
+               kzfree(smp);
                return NULL;
        }
 
@@ -1308,7 +1376,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
        if (IS_ERR(smp->tfm_cmac)) {
                BT_ERR("Unable to create CMAC crypto context");
                crypto_free_blkcipher(smp->tfm_aes);
-               kfree(smp);
+               kzfree(smp);
                return NULL;
        }
 
@@ -1604,15 +1672,15 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
        struct hci_dev *hdev = conn->hcon->hdev;
        u8 local_dist = 0, remote_dist = 0;
 
-       if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) {
+       if (hci_dev_test_flag(hdev, HCI_BONDABLE)) {
                local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
                remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
        }
 
-       if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
+       if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING))
                remote_dist |= SMP_DIST_ID_KEY;
 
-       if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
+       if (hci_dev_test_flag(hdev, HCI_PRIVACY))
                local_dist |= SMP_DIST_ID_KEY;
 
        if (!rsp) {
@@ -1664,22 +1732,29 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
        /* We didn't start the pairing, so match remote */
        auth = req->auth_req & AUTH_REQ_MASK(hdev);
 
-       if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
+       if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
            (auth & SMP_AUTH_BONDING))
                return SMP_PAIRING_NOTSUPP;
 
-       if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+       if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
                return SMP_AUTH_REQUIREMENTS;
 
        smp->preq[0] = SMP_CMD_PAIRING_REQ;
        memcpy(&smp->preq[1], req, sizeof(*req));
        skb_pull(skb, sizeof(*req));
 
+       /* If the remote side's OOB flag is set it means it has
+        * successfully received our local OOB data - therefore set the
+        * flag to indicate that local OOB is in use.
+        */
+       if (req->oob_flag == SMP_OOB_PRESENT)
+               set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags);
+
        /* SMP over BR/EDR requires special treatment */
        if (conn->hcon->type == ACL_LINK) {
                /* We must have a BR/EDR SC link */
                if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
-                   !test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
+                   !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
                        return SMP_CROSS_TRANSP_NOT_ALLOWED;
 
                set_bit(SMP_FLAG_SC, &smp->flags);
@@ -1737,6 +1812,13 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
        clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
 
+       /* Strictly speaking we shouldn't allow Pairing Confirm for the
+        * SC case, however some implementations incorrectly copy RFU auth
+        * req bits from our security request, which may create a false
+        * positive SC enablement.
+        */
+       SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
+
        if (test_bit(SMP_FLAG_SC, &smp->flags)) {
                SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
                /* Clear bits which are generated but not distributed */
@@ -1745,8 +1827,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
                return 0;
        }
 
-       SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-
        /* Request setup of TK */
        ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
        if (ret)
@@ -1761,7 +1841,26 @@ static u8 sc_send_public_key(struct smp_chan *smp)
 
        BT_DBG("");
 
-       if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) {
+       if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) {
+               struct l2cap_chan *chan = hdev->smp_data;
+               struct smp_dev *smp_dev;
+
+               if (!chan || !chan->data)
+                       return SMP_UNSPECIFIED;
+
+               smp_dev = chan->data;
+
+               memcpy(smp->local_pk, smp_dev->local_pk, 64);
+               memcpy(smp->local_sk, smp_dev->local_sk, 32);
+               memcpy(smp->lr, smp_dev->local_rand, 16);
+
+               if (smp_dev->debug_key)
+                       set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
+
+               goto done;
+       }
+
+       if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
                BT_DBG("Using debug keys");
                memcpy(smp->local_pk, debug_pk, 64);
                memcpy(smp->local_sk, debug_sk, 32);
@@ -1780,8 +1879,9 @@ static u8 sc_send_public_key(struct smp_chan *smp)
                }
        }
 
+done:
        SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
-       SMP_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
+       SMP_DBG("Local Public Key Y: %32phN", smp->local_pk + 32);
        SMP_DBG("Local Private Key:  %32phN", smp->local_sk);
 
        smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
@@ -1816,9 +1916,16 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 
        auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
 
-       if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+       if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
                return SMP_AUTH_REQUIREMENTS;
 
+       /* If the remote side's OOB flag is set it means it has
+        * successfully received our local OOB data - therefore set the
+        * flag to indicate that local OOB is in use.
+        */
+       if (rsp->oob_flag == SMP_OOB_PRESENT)
+               set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags);
+
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
 
@@ -1885,10 +1992,6 @@ static u8 sc_check_confirm(struct smp_chan *smp)
 
        BT_DBG("");
 
-       /* Public Key exchange must happen before any other steps */
-       if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
-               return SMP_UNSPECIFIED;
-
        if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
                return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
 
@@ -1901,6 +2004,47 @@ static u8 sc_check_confirm(struct smp_chan *smp)
        return 0;
 }
 
+/* Work-around for some implementations that incorrectly copy RFU bits
+ * from our security request and thereby create the impression that
+ * we're doing SC when in fact the remote doesn't support it.
+ */
+static int fixup_sc_false_positive(struct smp_chan *smp)
+{
+       struct l2cap_conn *conn = smp->conn;
+       struct hci_conn *hcon = conn->hcon;
+       struct hci_dev *hdev = hcon->hdev;
+       struct smp_cmd_pairing *req, *rsp;
+       u8 auth;
+
+       /* The issue is only observed when we're in slave role */
+       if (hcon->out)
+               return SMP_UNSPECIFIED;
+
+       if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
+               BT_ERR("Refusing SMP SC -> legacy fallback in SC-only mode");
+               return SMP_UNSPECIFIED;
+       }
+
+       BT_ERR("Trying to fall back to legacy SMP");
+
+       req = (void *) &smp->preq[1];
+       rsp = (void *) &smp->prsp[1];
+
+       /* Rebuild key dist flags which may have been cleared for SC */
+       smp->remote_key_dist = (req->init_key_dist & rsp->resp_key_dist);
+
+       auth = req->auth_req & AUTH_REQ_MASK(hdev);
+
+       if (tk_request(conn, 0, auth, rsp->io_capability, req->io_capability)) {
+               BT_ERR("Failed to fall back to legacy SMP");
+               return SMP_UNSPECIFIED;
+       }
+
+       clear_bit(SMP_FLAG_SC, &smp->flags);
+
+       return 0;
+}
+
 static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct l2cap_chan *chan = conn->smp;
@@ -1914,8 +2058,19 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
        memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
        skb_pull(skb, sizeof(smp->pcnf));
 
-       if (test_bit(SMP_FLAG_SC, &smp->flags))
-               return sc_check_confirm(smp);
+       if (test_bit(SMP_FLAG_SC, &smp->flags)) {
+               int ret;
+
+               /* Public Key exchange must happen before any other steps */
+               if (test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
+                       return sc_check_confirm(smp);
+
+               BT_ERR("Unexpected SMP Pairing Confirm");
+
+               ret = fixup_sc_false_positive(smp);
+               if (ret)
+                       return ret;
+       }
 
        if (conn->hcon->out) {
                smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
@@ -2086,7 +2241,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
        auth = rp->auth_req & AUTH_REQ_MASK(hdev);
 
-       if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
+       if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
                return SMP_AUTH_REQUIREMENTS;
 
        if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
@@ -2107,7 +2262,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        if (!smp)
                return SMP_UNSPECIFIED;
 
-       if (!test_bit(HCI_BONDABLE, &hcon->hdev->dev_flags) &&
+       if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
            (auth & SMP_AUTH_BONDING))
                return SMP_PAIRING_NOTSUPP;
 
@@ -2141,7 +2296,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
        chan = conn->smp;
 
-       if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
+       if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED))
                return 1;
 
        if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
@@ -2170,7 +2325,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
        authreq = seclevel_to_authreq(sec_level);
 
-       if (test_bit(HCI_SC_ENABLED, &hcon->hdev->dev_flags))
+       if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
                authreq |= SMP_AUTH_SC;
 
        /* Require MITM if IO Capability allows or the security level
@@ -2374,7 +2529,8 @@ static u8 sc_select_method(struct smp_chan *smp)
        struct smp_cmd_pairing *local, *remote;
        u8 local_mitm, remote_mitm, local_io, remote_io, method;
 
-       if (test_bit(SMP_FLAG_OOB, &smp->flags))
+       if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags) ||
+           test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags))
                return REQ_OOB;
 
        /* The preq/prsp contain the raw Pairing Request/Response PDUs
@@ -2428,6 +2584,16 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
 
        memcpy(smp->remote_pk, key, 64);
 
+       if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags)) {
+               err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
+                            smp->rr, 0, cfm.confirm_val);
+               if (err)
+                       return SMP_UNSPECIFIED;
+
+               if (memcmp(cfm.confirm_val, smp->pcnf, 16))
+                       return SMP_CONFIRM_FAILED;
+       }
+
        /* Non-initiating device sends its public key after receiving
         * the key from the initiating device.
         */
@@ -2438,7 +2604,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
        }
 
        SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
-       SMP_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
+       SMP_DBG("Remote Public Key Y: %32phN", smp->remote_pk + 32);
 
        if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
                return SMP_UNSPECIFIED;
@@ -2476,14 +2642,6 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
        }
 
        if (smp->method == REQ_OOB) {
-               err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
-                            smp->rr, 0, cfm.confirm_val);
-               if (err)
-                       return SMP_UNSPECIFIED;
-
-               if (memcmp(cfm.confirm_val, smp->pcnf, 16))
-                       return SMP_CONFIRM_FAILED;
-
                if (hcon->out)
                        smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
                                     sizeof(smp->prnd), smp->prnd);
@@ -2556,6 +2714,8 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
 
        if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
                put_unaligned_le32(hcon->passkey_notify, r);
+       else if (smp->method == REQ_OOB)
+               memcpy(r, smp->lr, 16);
 
        err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
                     io_cap, remote_addr, local_addr, e);
@@ -2606,7 +2766,7 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
        if (skb->len < 1)
                return -EILSEQ;
 
-       if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
+       if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) {
                reason = SMP_PAIRING_NOTSUPP;
                goto done;
        }
@@ -2744,16 +2904,16 @@ static void bredr_pairing(struct l2cap_chan *chan)
                return;
 
        /* Secure Connections support must be enabled */
-       if (!test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
+       if (!hci_dev_test_flag(hdev, HCI_SC_ENABLED))
                return;
 
        /* BR/EDR must use Secure Connections for SMP */
        if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
-           !test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
+           !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
                return;
 
        /* If our LE support is not enabled don't do anything */
-       if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+       if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
                return;
 
        /* Don't bother if remote LE support is not enabled */
@@ -2930,27 +3090,49 @@ static const struct l2cap_ops smp_root_chan_ops = {
 static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
 {
        struct l2cap_chan *chan;
-       struct crypto_blkcipher *tfm_aes;
+       struct smp_dev *smp;
+       struct crypto_blkcipher *tfm_aes;
+       struct crypto_hash *tfm_cmac;
 
        if (cid == L2CAP_CID_SMP_BREDR) {
-               tfm_aes = NULL;
+               smp = NULL;
                goto create_chan;
        }
 
-       tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0);
+       smp = kzalloc(sizeof(*smp), GFP_KERNEL);
+       if (!smp)
+               return ERR_PTR(-ENOMEM);
+
+       tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm_aes)) {
-               BT_ERR("Unable to create crypto context");
+               BT_ERR("Unable to create ECB crypto context");
+               kzfree(smp);
                return ERR_CAST(tfm_aes);
        }
 
+       tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm_cmac)) {
+               BT_ERR("Unable to create CMAC crypto context");
+               crypto_free_blkcipher(tfm_aes);
+               kzfree(smp);
+               return ERR_CAST(tfm_cmac);
+       }
+
+       smp->tfm_aes = tfm_aes;
+       smp->tfm_cmac = tfm_cmac;
+
 create_chan:
        chan = l2cap_chan_create();
        if (!chan) {
-               crypto_free_blkcipher(tfm_aes);
+               if (smp) {
+                       crypto_free_blkcipher(smp->tfm_aes);
+                       crypto_free_hash(smp->tfm_cmac);
+                       kzfree(smp);
+               }
                return ERR_PTR(-ENOMEM);
        }
 
-       chan->data = tfm_aes;
+       chan->data = smp;
 
        l2cap_add_scid(chan, cid);
 
@@ -2983,14 +3165,18 @@ create_chan:
 
 static void smp_del_chan(struct l2cap_chan *chan)
 {
-       struct crypto_blkcipher *tfm_aes;
+       struct smp_dev *smp;
 
        BT_DBG("chan %p", chan);
 
-       tfm_aes = chan->data;
-       if (tfm_aes) {
+       smp = chan->data;
+       if (smp) {
                chan->data = NULL;
-               crypto_free_blkcipher(tfm_aes);
+               if (smp->tfm_aes)
+                       crypto_free_blkcipher(smp->tfm_aes);
+               if (smp->tfm_cmac)
+                       crypto_free_hash(smp->tfm_cmac);
+               kzfree(smp);
        }
 
        l2cap_chan_put(chan);
@@ -3003,7 +3189,7 @@ static ssize_t force_bredr_smp_read(struct file *file,
        struct hci_dev *hdev = file->private_data;
        char buf[3];
 
-       buf[0] = test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags) ? 'Y': 'N';
+       buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP) ? 'Y': 'N';
        buf[1] = '\n';
        buf[2] = '\0';
        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -3025,7 +3211,7 @@ static ssize_t force_bredr_smp_write(struct file *file,
        if (strtobool(buf, &enable))
                return -EINVAL;
 
-       if (enable == test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags))
+       if (enable == hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
                return -EALREADY;
 
        if (enable) {
@@ -3044,7 +3230,7 @@ static ssize_t force_bredr_smp_write(struct file *file,
                smp_del_chan(chan);
        }
 
-       change_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags);
+       hci_dev_change_flag(hdev, HCI_FORCE_BREDR_SMP);
 
        return count;
 }