Bluetooth: Add function for generating LE SC out-of-band data
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 16 Mar 2015 08:10:22 +0000 (01:10 -0700)
committerJohan Hedberg <johan.hedberg@intel.com>
Mon, 16 Mar 2015 08:31:27 +0000 (10:31 +0200)
This patch adds a smp_generate_oob function that allows to create
local out-of-band data that can be used for pairing and also provides
the confirmation and random value.

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

index 12e9c833885b86e14578ea271f2a2d84e5cc5459..1669e7127e2ee6eec3bf1ad872a3d38fad69b23c 100644 (file)
@@ -74,6 +74,12 @@ enum {
 };
 
 struct smp_dev {
+       /* Secure Connections OOB data */
+       u8                      local_pk[64];
+       u8                      local_sk[32];
+       u8                      local_rr[16];
+       bool                    debug_key;
+
        struct crypto_blkcipher *tfm_aes;
        struct crypto_hash      *tfm_cmac;
 };
@@ -526,6 +532,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_rr, 16);
+
+       err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk,
+                    smp->local_rr, 0, hash);
+       if (err < 0)
+               return err;
+
+       memcpy(rand, smp->local_rr, 16);
+
+       return 0;
+}
+
 static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
        struct l2cap_chan *chan = conn->smp;
index 60c5b73fcb4b26e3aab32604b58809ca30a4e6f4..6cf872563ea71d425dd1798314765edb56d39a51 100644 (file)
@@ -188,6 +188,7 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
                     const bdaddr_t *bdaddr);
 int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa);
+int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]);
 
 int smp_register(struct hci_dev *hdev);
 void smp_unregister(struct hci_dev *hdev);