]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/bluetooth/smp.c
Bluetooth: Fix SMP debug key handling
[mirror_ubuntu-artful-kernel.git] / net / bluetooth / smp.c
index 0c2214a418163da58fb7e610a1bdcce39e47b16f..a7b973b867c8ef26d3e3e631af47f1ebddf83a15 100644 (file)
 #include "ecc.h"
 #include "smp.h"
 
+/* Low-level debug macros to be used for stuff that we don't want
+ * accidentially in dmesg, i.e. the values of the various crypto keys
+ * and the inputs & outputs of crypto functions.
+ */
+#ifdef DEBUG
+#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
+                                ##__VA_ARGS__)
+#else
+#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
+                                   ##__VA_ARGS__)
+#endif
+
 #define SMP_ALLOW_CMD(smp, code)       set_bit(code, &smp->allow_cmd)
 
 /* Keys which are not distributed with Secure Connections */
@@ -71,6 +83,7 @@ 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              enc_key_size;
        u8              remote_key_dist;
        bdaddr_t        id_addr;
@@ -128,6 +141,10 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
                dst[len - 1 - i] = src[i];
 }
 
+/* The following functions map to the LE SC SMP crypto functions
+ * AES-CMAC, f4, f5, f6, g2 and h6.
+ */
+
 static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
                    size_t len, u8 mac[16])
 {
@@ -153,8 +170,8 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
        swap_buf(k, tmp, 16);
        swap_buf(m, msg_msb, len);
 
-       BT_DBG("msg (len %zu) %*phN", len, (int) len, m);
-       BT_DBG("key %16phN", k);
+       SMP_DBG("msg (len %zu) %*phN", len, (int) len, m);
+       SMP_DBG("key %16phN", k);
 
        err = crypto_hash_setkey(tfm, tmp, 16);
        if (err) {
@@ -178,7 +195,7 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
 
        swap_buf(mac_msb, mac, 16);
 
-       BT_DBG("mac %16phN", mac);
+       SMP_DBG("mac %16phN", mac);
 
        return 0;
 }
@@ -189,9 +206,9 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
        u8 m[65];
        int err;
 
-       BT_DBG("u %32phN", u);
-       BT_DBG("v %32phN", v);
-       BT_DBG("x %16phN z %02x", x, z);
+       SMP_DBG("u %32phN", u);
+       SMP_DBG("v %32phN", v);
+       SMP_DBG("x %16phN z %02x", x, z);
 
        m[0] = z;
        memcpy(m + 1, v, 32);
@@ -201,7 +218,7 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
        if (err)
                return err;
 
-       BT_DBG("res %16phN", res);
+       SMP_DBG("res %16phN", res);
 
        return err;
 }
@@ -222,15 +239,15 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
        u8 m[53], t[16];
        int err;
 
-       BT_DBG("w %32phN", w);
-       BT_DBG("n1 %16phN n2 %16phN", n1, n2);
-       BT_DBG("a1 %7phN a2 %7phN", a1, a2);
+       SMP_DBG("w %32phN", w);
+       SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
+       SMP_DBG("a1 %7phN a2 %7phN", a1, a2);
 
        err = aes_cmac(tfm_cmac, salt, w, 32, t);
        if (err)
                return err;
 
-       BT_DBG("t %16phN", t);
+       SMP_DBG("t %16phN", t);
 
        memcpy(m, length, 2);
        memcpy(m + 2, a2, 7);
@@ -245,7 +262,7 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
        if (err)
                return err;
 
-       BT_DBG("mackey %16phN", mackey);
+       SMP_DBG("mackey %16phN", mackey);
 
        m[52] = 1; /* Counter */
 
@@ -253,7 +270,7 @@ static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
        if (err)
                return err;
 
-       BT_DBG("ltk %16phN", ltk);
+       SMP_DBG("ltk %16phN", ltk);
 
        return 0;
 }
@@ -266,9 +283,9 @@ static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16],
        u8 m[65];
        int err;
 
-       BT_DBG("w %16phN", w);
-       BT_DBG("n1 %16phN n2 %16phN", n1, n2);
-       BT_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
+       SMP_DBG("w %16phN", w);
+       SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
+       SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
 
        memcpy(m, a2, 7);
        memcpy(m + 7, a1, 7);
@@ -292,9 +309,9 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
        u8 m[80], tmp[16];
        int err;
 
-       BT_DBG("u %32phN", u);
-       BT_DBG("v %32phN", v);
-       BT_DBG("x %16phN y %16phN", x, y);
+       SMP_DBG("u %32phN", u);
+       SMP_DBG("v %32phN", v);
+       SMP_DBG("x %16phN y %16phN", x, y);
 
        memcpy(m, y, 16);
        memcpy(m + 16, v, 32);
@@ -307,11 +324,31 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
        *val = get_unaligned_le32(tmp);
        *val %= 1000000;
 
-       BT_DBG("val %06u", *val);
+       SMP_DBG("val %06u", *val);
 
        return 0;
 }
 
+static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
+                 const u8 key_id[4], u8 res[16])
+{
+       int err;
+
+       SMP_DBG("w %16phN key_id %4phN", w, key_id);
+
+       err = aes_cmac(tfm_cmac, w, key_id, 4, 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.
+ */
+
 static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 {
        struct blkcipher_desc desc;
@@ -351,23 +388,65 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
        return err;
 }
 
-static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
-                 const u8 key_id[4], u8 res[16])
+static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+                 const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
+                 const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
 {
+       u8 p1[16], p2[16];
        int err;
 
-       BT_DBG("w %16phN key_id %4phN", w, key_id);
+       memset(p1, 0, 16);
 
-       err = aes_cmac(tfm_cmac, w, key_id, 4, res);
-       if (err)
+       /* p1 = pres || preq || _rat || _iat */
+       p1[0] = _iat;
+       p1[1] = _rat;
+       memcpy(p1 + 2, preq, 7);
+       memcpy(p1 + 9, pres, 7);
+
+       /* p2 = padding || ia || ra */
+       memcpy(p2, ra, 6);
+       memcpy(p2 + 6, ia, 6);
+       memset(p2 + 12, 0, 4);
+
+       /* res = r XOR p1 */
+       u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+       /* res = e(k, res) */
+       err = smp_e(tfm_aes, k, res);
+       if (err) {
+               BT_ERR("Encrypt data error");
                return err;
+       }
 
-       BT_DBG("res %16phN", res);
+       /* res = res XOR p2 */
+       u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+       /* res = e(k, res) */
+       err = smp_e(tfm_aes, k, res);
+       if (err)
+               BT_ERR("Encrypt data error");
+
+       return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
+                 const u8 r1[16], const u8 r2[16], u8 _r[16])
+{
+       int err;
+
+       /* Just least significant octets from r1 and r2 are considered */
+       memcpy(_r, r2, 8);
+       memcpy(_r + 8, r1, 8);
+
+       err = smp_e(tfm_aes, k, _r);
+       if (err)
+               BT_ERR("Encrypt data error");
 
        return err;
 }
 
-static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
+static int smp_ah(struct crypto_blkcipher *tfm, const u8 irk[16],
+                 const u8 r[3], u8 res[3])
 {
        u8 _res[16];
        int err;
@@ -393,7 +472,8 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
        return 0;
 }
 
-bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
+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;
@@ -414,7 +494,7 @@ bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
        return !memcmp(bdaddr->b, hash, 3);
 }
 
-int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
+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;
@@ -439,63 +519,6 @@ int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
        return 0;
 }
 
-static int smp_c1(struct crypto_blkcipher *tfm_aes, u8 k[16], u8 r[16],
-                 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat,
-                 bdaddr_t *ra, u8 res[16])
-{
-       u8 p1[16], p2[16];
-       int err;
-
-       memset(p1, 0, 16);
-
-       /* p1 = pres || preq || _rat || _iat */
-       p1[0] = _iat;
-       p1[1] = _rat;
-       memcpy(p1 + 2, preq, 7);
-       memcpy(p1 + 9, pres, 7);
-
-       /* p2 = padding || ia || ra */
-       memcpy(p2, ra, 6);
-       memcpy(p2 + 6, ia, 6);
-       memset(p2 + 12, 0, 4);
-
-       /* res = r XOR p1 */
-       u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
-
-       /* res = e(k, res) */
-       err = smp_e(tfm_aes, k, res);
-       if (err) {
-               BT_ERR("Encrypt data error");
-               return err;
-       }
-
-       /* res = res XOR p2 */
-       u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
-
-       /* res = e(k, res) */
-       err = smp_e(tfm_aes, k, res);
-       if (err)
-               BT_ERR("Encrypt data error");
-
-       return err;
-}
-
-static int smp_s1(struct crypto_blkcipher *tfm_aes, u8 k[16], u8 r1[16],
-                 u8 r2[16], u8 _r[16])
-{
-       int err;
-
-       /* Just least significant octets from r1 and r2 are considered */
-       memcpy(_r, r2, 8);
-       memcpy(_r + 8, r1, 8);
-
-       err = smp_e(tfm_aes, k, _r);
-       if (err)
-               BT_ERR("Encrypt data error");
-
-       return err;
-}
-
 static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
        struct l2cap_chan *chan = conn->smp;
@@ -599,7 +622,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                if (oob_data) {
                        set_bit(SMP_FLAG_OOB, &smp->flags);
                        oob_flag = SMP_OOB_PRESENT;
-                       memcpy(smp->rrnd, oob_data->rand256, 16);
+                       memcpy(smp->rr, oob_data->rand256, 16);
                        memcpy(smp->pcnf, oob_data->hash256, 16);
                }
 
@@ -647,6 +670,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
 {
        struct l2cap_chan *chan = conn->smp;
        struct smp_chan *smp = chan->data;
+       struct hci_conn *hcon = conn->hcon;
        bool complete;
 
        BUG_ON(!smp);
@@ -654,7 +678,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
        cancel_delayed_work_sync(&smp->security_timer);
 
        complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
-       mgmt_smp_complete(conn->hcon, complete);
+       mgmt_smp_complete(hcon, complete);
 
        kfree(smp->csrk);
        kfree(smp->slave_csrk);
@@ -663,6 +687,16 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
        crypto_free_blkcipher(smp->tfm_aes);
        crypto_free_hash(smp->tfm_cmac);
 
+       /* Ensure that we don't leave any debug key around if debug key
+        * 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)) {
+               list_del_rcu(&smp->ltk->list);
+               kfree_rcu(smp->ltk, rcu);
+               smp->ltk = NULL;
+       }
+
        /* If pairing failed clean up any keys we might have */
        if (!complete) {
                if (smp->ltk) {
@@ -683,7 +717,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
 
        chan->data = NULL;
        kfree(smp);
-       hci_conn_drop(conn->hcon);
+       hci_conn_drop(hcon);
 }
 
 static void smp_failure(struct l2cap_conn *conn, u8 reason)
@@ -1334,6 +1368,9 @@ static void sc_dhkey_check(struct smp_chan *smp)
        if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
                put_unaligned_le32(hcon->passkey_notify, r);
 
+       if (smp->method == REQ_OOB)
+               memcpy(r, smp->rr, 16);
+
        smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
               local_addr, remote_addr, check.e);
 
@@ -1738,9 +1775,9 @@ static u8 sc_send_public_key(struct smp_chan *smp)
                }
        }
 
-       BT_DBG("Local Public Key X: %32phN", smp->local_pk);
-       BT_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
-       BT_DBG("Local Private Key:  %32phN", smp->local_sk);
+       SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
+       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);
 
@@ -1910,6 +1947,14 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
        if (!test_bit(SMP_FLAG_SC, &smp->flags))
                return smp_random(smp);
 
+       if (smp->method == REQ_OOB) {
+               if (!hcon->out)
+                       smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
+                                    sizeof(smp->prnd), smp->prnd);
+               SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
+               goto mackey_and_ltk;
+       }
+
        /* Passkey entry has special treatment */
        if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
                return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
@@ -1940,12 +1985,13 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
                nb   = smp->prnd;
        }
 
+mackey_and_ltk:
        /* Generate MacKey and LTK */
        err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk);
        if (err)
                return SMP_UNSPECIFIED;
 
-       if (smp->method == JUST_WORKS) {
+       if (smp->method == JUST_WORKS || smp->method == REQ_OOB) {
                if (hcon->out) {
                        sc_dhkey_check(smp);
                        SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
@@ -2314,6 +2360,9 @@ 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))
+               return REQ_OOB;
+
        /* The preq/prsp contain the raw Pairing Request/Response PDUs
         * which are needed as inputs to some crypto functions. To get
         * the "struct smp_cmd_pairing" from them we need to skip the
@@ -2374,13 +2423,13 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
                        return err;
        }
 
-       BT_DBG("Remote Public Key X: %32phN", smp->remote_pk);
-       BT_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
+       SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
+       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;
 
-       BT_DBG("DHKey %32phN", smp->dhkey);
+       SMP_DBG("DHKey %32phN", smp->dhkey);
 
        set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
 
@@ -2412,6 +2461,24 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
                return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
        }
 
+       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);
+
+               SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
+
+               return 0;
+       }
+
        if (hcon->out)
                SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);